Part 1: clean and normalize data

My data is from GSE84054 (Goh et al. 2017). Title: Transcriptome profiling of ER+ breast cancer primary tumor and its tumorsphere derivative. Overview of the dataset: 12 ER+ primary tumor and tumorspheres. The objective of the authors were to find genes differentially expressed between these two groups.

Download data

# Download dataset
datafile <- "GSE84054_Rawcount_12patientER.txt.gz"
if (!file.exists(datafile)) {
    datafile <- GEOquery::getGEOSuppFiles('GSE84054', makeDirectory = FALSE)
}
expr <- read.delim(datafile,header=TRUE,check.names=FALSE)
dim(expr) # 57268    25
[1] 57268    25
# Display rawcount file
kable(expr[1:5,1:10], format = "html")
RHB037 RHB038 RHB041 RHB049 RHB050 RHB052 RHB053 RHB350 RHB351
ENSG00000000003 2561 2141 1186 233 742 879 2946 745 273
ENSG00000000005 0 3 12 9 0 1 1 1 8
ENSG00000000419 1170 1299 1560 210 901 737 990 508 332
ENSG00000000457 387 408 199 83 338 242 230 118 65
ENSG00000000460 217 168 121 41 189 94 94 67 34

Check GENEID duplications

It is important to check for GENE ID duplications because we are going to map them to hg19. We need to prevent one to multiple or multiple to one scenarios. It turns out we do not have duplicated GENEIDs.

Explore

Filter out low counts

The objective is to remove the ones with low counts. Why? Filter weakly expressed and noninformative (e.g., non-aligned) features. How? We translate out counts into counts per million cpm(),remove features without at least 1 read per million in n of the samples, where n is the size of the smallest group of replicates

# translate out counts into counts per million
cpms = cpm(expr[,2:25])
rownames(cpms) <- expr[,1]
# get rid of low counts
keep = rowSums(cpms > 1) >= 3
expr_filtered <- expr[keep,]
outliers_removed <- nrow(expr) - nrow(expr_filtered) # 37395
dim(expr_filtered) # 19873    25
[1] 19873    25
# Display rawcount file
kable(expr_filtered[1:5,1:10], format = "html")
RHB037 RHB038 RHB041 RHB049 RHB050 RHB052 RHB053 RHB350 RHB351
1 ENSG00000000003 2561 2141 1186 233 742 879 2946 745 273
3 ENSG00000000419 1170 1299 1560 210 901 737 990 508 332
4 ENSG00000000457 387 408 199 83 338 242 230 118 65
5 ENSG00000000460 217 168 121 41 189 94 94 67 34
6 ENSG00000000938 45 134 61 132 72 77 79 28 66

Explore: filtered

Identifier mapping

ensembl_id <- as.character(expr_filtered[,1])

EnsDb_trans_ensembl<- ensembldb::select(EnsDb.Hsapiens.v75,
                                         keys = ensembl_id, 
                                         columns="SYMBOL",
                                         keytype="GENEID")

data.frame(EnsDb_trans_ensembl)
nrow(EnsDb_trans_ensembl) # 19856 ids mapped

Unmapped GENEIDs

The 17 unmapped gene ids are actually duplicates. The reason why the previous check did not catch them was because if we change the “R” to “0”, they can be detected. (They are exactly same, except locating on the Y chromosome). So here I am just going to remove them.

test_filtered <- expr_filtered

# merge mapped df EnsDb_trans_ensembl and unmapped df test_filtered
test_filtered <- merge(EnsDb_trans_ensembl,
                       test_filtered, 
                       by.x=1, by.y=1, all.y=TRUE )
# nrow(test_filtered) # 19873
kable(test_filtered[1:5, 1:5], format = "html")  

GENEID SYMBOL RHB037 RHB038 RHB041
ENSG00000000003 TSPAN6 2561 2141 1186
ENSG00000000419 DPM1 1170 1299 1560
ENSG00000000457 SCYL3 387 408 199
ENSG00000000460 C1orf112 217 168 121
ENSG00000000938 FGR 45 134 61


# duplicated ensembl id
dup_gene_id <- (test_filtered$GENEID[which(is.na(test_filtered$SYMBOL))])
length(dup_gene_id) # 17
[1] 17
# display the unmapped ensembl ids
kable(test_filtered[which(is.na(test_filtered$SYMBOL)),][,1:5], format = "html")

GENEID SYMBOL RHB037 RHB038 RHB041
19857 ENSGR0000002586 NA 432 2485 3880
19858 ENSGR0000124333 NA 424 555 251
19859 ENSGR0000167393 NA 77 20 35
19860 ENSGR0000168939 NA 48 27 12
19861 ENSGR0000169084 NA 260 278 235
19862 ENSGR0000169093 NA 56 102 111
19863 ENSGR0000169100 NA 9130 5843 12001
19864 ENSGR0000178605 NA 139 83 185
19865 ENSGR0000182162 NA 3 50 67
19866 ENSGR0000182378 NA 68 37 215
19867 ENSGR0000185203 NA 8 47 33
19868 ENSGR0000185291 NA 28 224 104
19869 ENSGR0000197976 NA 62 134 106
19870 ENSGR0000198223 NA 47 251 82
19871 ENSGR0000214717 NA 179 303 406
19872 ENSGR0000223773 NA 33 86 80
19873 ENSGR0000226179 NA 55 23 11


# Since I have proved it, I will directly exclude them from expr_filtered
test_filtered <- test_filtered[-which(is.na(test_filtered$SYMBOL)),]
nrow(test_filtered) # 19856
[1] 19856
expr_filtered <- test_filtered
nrow(expr_filtered) # 19856
[1] 19856
rownames(expr_filtered) <- 1:nrow(expr_filtered)
(num_dup_id <- length(expr_filtered$GENEID[which(duplicated(expr_filtered$GENEID))])) # 0 duplicated
[1] 0
all(EnsDb_trans_ensembl$GENEID == expr_filtered$GENEID) # TRUE
[1] TRUE
all(EnsDb_trans_ensembl$SYMBOL == expr_filtered$SYMBOL) # TRUE
[1] TRUE

Group samples

Categorize the samples based on their cell types.

samples_filtered <- data.frame("patients" = 1:24,"cell_type"=1:24)
rownames(samples_filtered) <- colnames(expr_filtered)[3:ncol(expr_filtered)]

for (i in 1:12){
  samples_filtered$cell_type[i] = "Primary Tumour"
  samples_filtered$patients[i] = i
  samples_filtered$patients[i + 12] = i
}

for (j in 13:24){
  samples_filtered$cell_type[j] = "Sphere"
}

# Add cell_type to sample names
cell_type_indicator <- substring(samples_filtered$cell_type,1,1) # first characters of cell types
rownames(samples_filtered) <- paste0(rownames(samples_filtered), sep="_", cell_type_indicator)

# display grouped format
kable(samples_filtered, format = "html")  
patients cell_type
RHB037_P 1 Primary Tumour
RHB038_P 2 Primary Tumour
RHB041_P 3 Primary Tumour
RHB049_P 4 Primary Tumour
RHB050_P 5 Primary Tumour
RHB052_P 6 Primary Tumour
RHB053_P 7 Primary Tumour
RHB350_P 8 Primary Tumour
RHB351_P 9 Primary Tumour
RHB353_P 10 Primary Tumour
RHB354_P 11 Primary Tumour
RHB355_P 12 Primary Tumour
RHB031_S 1 Sphere
RHB032_S 2 Sphere
RHB035_S 3 Sphere
RHB043_S 4 Sphere
RHB044_S 5 Sphere
RHB046_S 6 Sphere
RHB047_S 7 Sphere
RHB344_S 8 Sphere
RHB345_S 9 Sphere
RHB347_S 10 Sphere
RHB348_S 11 Sphere
RHB349_S 12 Sphere

GENE name duplication

  • In A1 I showed that there are 41 duplications (12 unique ones), Ruth sugguested to keep them because it is a very small percent. But I find the MDS plot (color by sample) will be a little messy if I keep them. But color by patient totaly works.
dup_gene_name <- sort(table(expr_filtered$SYMBOL),decreasing = TRUE)
length(dup_gene_name[which(dup_gene_name>1)]) # 12

Apply normalization on expr_filtered

# need a matrix with only values
filtered_data_matrix <- as.matrix(expr_filtered[,3:ncol(expr_filtered)])

# Rownames be the ensembl id
rownames(filtered_data_matrix) <- expr_filtered$GENEID

# DEGList object
d <- DGEList(counts=filtered_data_matrix, group=samples_filtered$cell_type)

# Normalization
d <- calcNormFactors(d)

# get normalized counts
normalized_counts <- cpm(d)

normalized_counts <- data.frame(normalized_counts)
normalized_counts <- cbind("SYMBOL" = expr_filtered$SYMBOL, normalized_counts)
normalized_counts <- cbind("GENEID" = expr_filtered$GENEID, normalized_counts)
nrow(normalized_counts) # 19856
[1] 19856
# HUGO symbols as rownames of the dataframe
kable(normalized_counts[1:5,1:5], format = "html")

GENEID SYMBOL RHB037 RHB038 RHB041
ENSG00000000003 ENSG00000000003 TSPAN6 79.809196 63.375225 37.719858
ENSG00000000419 ENSG00000000419 DPM1 36.461054 38.451386 49.614654
ENSG00000000457 ENSG00000000457 SCYL3 12.060195 12.077110 6.329049
ENSG00000000460 ENSG00000000460 C1orf112 6.762435 4.972927 3.848316
ENSG00000000938 ENSG00000000938 FGR 1.402348 3.966502 1.940060

# All rows have a unique HUGO symbols, 
sum(duplicated(rownames(normalized_counts))) # 0
[1] 0
write.table(normalized_counts, file="GSE84054_normalized_count.txt")

Part 2: DE + thresholded over-representation analysis

The objective of this second assignment is to explore the differentially expressed genes from the cleaned and normalized data in A1. Then rank the thresholded over-representation analysis to highlight the top terms / dominant themes in the top set of genes. Lastly, compare my result with the original literature and find some other supports as well for my result if possible. I make some changes to my assignment one and stored the file as “ammended_A1.Rmd” and imported it here. I will demonstrate briefly what I have changed in general workflow in A1. My summary of the paper can be found at my journal or in A1

Load data

Loaded my normalized data from A1.

normalized_count_data <- read.table(file="GSE84054_normalized_count.txt")
kable(normalized_count_data[1:5, 1:5], type="html")
GENEID SYMBOL RHB037 RHB038 RHB041
ENSG00000000003 ENSG00000000003 TSPAN6 79.809196 63.375225 37.719858
ENSG00000000419 ENSG00000000419 DPM1 36.461054 38.451386 49.614654
ENSG00000000457 ENSG00000000457 SCYL3 12.060195 12.077110 6.329049
ENSG00000000460 ENSG00000000460 C1orf112 6.762435 4.972927 3.848316
ENSG00000000938 ENSG00000000938 FGR 1.402348 3.966502 1.940060

Explore: Normalized

Differential expression

  1. Calculate p-values for each of the genes in your expression set. How many genes were significantly differentially expressed? What thresholds did you use and why?
  • There are 7464 genes that are below the p-value. The threshold I used is 0.05 because this is what the authors of the paper sugguested that they use.
  1. Multiple hypothesis testing - correct your p-values using a multiple hypothesis correction method. Which method did you use? And Why? How many genes passed correction?
  • I used FDR correction which is also what the authors of the paper specified. 5033 genes passed the correction. Both the p-value and the correction data are based on the edgeR package, not the limma package. I used the limma package up till the point of calculating differential expression like what is sugguested on the lecture notes.
  1. Show the amount of differentially expressed genes using an MA Plot or a Volcano plot. Highlight genes of interest.
  • I showed a volcano plot using my edgeR fitted data and highlighed the upregulated to be red and down regulated to be blue.
  1. Visualize your top hits using a heatmap. Do you conditions cluster together? Explain why or why not.
  • My data clustered perfectly according to their cell types which is what my model design based on. My interpretation for the graph would be that since the colors are opposite to each other in the two different cell types, it means that the genes that are upregulated in tumoursphere would be down regulated in primary tumour samples. The shows a great results that the upregulated genes can be potential biomarkers to track if tumoursphere is present or not.

1. Choice of factors in my model

  • I created the MDS by both using “cell_type” and “cell_type” and “patient”. The comparison between the two models is fairly clear: we should only depend on the factor “cell_type”, since there seems to be no correlation with each patient.

2. Define my model design

Based on the two models in part1, I decide to base my model only on “cell_type”

model_design <- model.matrix(~ samples$cell_type)
kable(model_design, type="html")

3. Set up EdgeR object

d = DGEList(counts=filtered_data_matrix, group=samples$cell_type)
d <- estimateDisp(d, model_design_pat)

4. Test whether my data is suitable for edgeR - MeanVar plot

I have shown that my data is suitable for using edgeR for further analysis. The data follows the binomial distribution.

5. Estimate dispersion - BCV plot

The individual dots represent each gene and the blue line is the overall trend line.

6. Genes pass threshold and FDR correction

I used Quasi-likelihood models to fit my data and used QLFTest to test for differential expression. The Quasi-likelihood compares two conditions (primary tumour and tumoursphere) and shows the up and down-regulated genes. The result below that are sorted by p-value. I also inspected the number of genes that satisty my threshold and correction. I choose to use FDR correction based on the paper as well(Goh et al. 2017) . There are 7467 genes pass the p-value = 0.05, and 5033 genes that pass the FDR correction.

logFC logCPM F PValue FDR
ENSG00000133574 -10.864552 4.3344790 211.3416 0 0
ENSG00000106483 -12.504407 5.1136480 184.1976 0 0
ENSG00000179144 -10.957441 4.7967197 159.9882 0 0
ENSG00000163563 -9.261757 3.3981949 156.9675 0 0
ENSG00000130300 -12.870252 5.0189032 153.4504 0 0
ENSG00000211668 -11.278848 3.4432853 146.3944 0 0
ENSG00000147113 -10.742034 3.3588694 141.1675 0 0
ENSG00000167286 -10.447530 2.6237953 140.2040 0 0
ENSG00000120279 -9.829420 2.4408378 138.9715 0 0
ENSG00000106952 -7.721763 -0.0200685 138.2581 0 0
x
BH
x
samples$cell_typeSphere
x
glm

7. Up and down-regulated genes

I determined the number of up-regulated genes by selecting every gene that does not pass my p-value: 0.05, and also have a positive log fold change. Down-regulated genes are selected in the same way with a negative log fold change. Stored these data for later enrichment analysis on gProfileR.

# number of genes that are up regulated
length(which(qlf_output_hits$table$PValue < 0.05 
             & qlf_output_hits$table$logFC > 0)) # 1897

# number of genes that are down regulated
length(which(qlf_output_hits$table$PValue < 0.05  
             & qlf_output_hits$table$logFC < 0)) # 5570

# Get those up and down-regulated genes
qlf_output_hits_withgn <- merge(expr_filtered[,1:2],qlf_output_hits, by.x=1, by.y = 0)

upregulated_genes <- qlf_output_hits_withgn$GENEID[which(qlf_output_hits$table$PValue < 0.05 
                                                         & qlf_output_hits$table$logFC > 0)]

downregulated_genes <-qlf_output_hits_withgn$GENEID[which(qlf_output_hits$table$PValue < 0.05 
                                                           & qlf_output_hits$table$logFC < 0)]


# store data - all differentially expressed
unreg_genes_copy <- data.frame(upregulated_genes)
downreg_genes_copy <- data.frame(downregulated_genes)
names(unreg_genes_copy) <- names(downreg_genes_copy)
all_de <- rbind(unreg_genes_copy, downreg_genes_copy)
colnames(all_de) <- "all_de"
write.table(x=all_de,
            file="all_expr_de_genes.txt",sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)

# up regulated
write.table(x=upregulated_genes,
            file="expr_upregulated_genes.txt",sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)

# down regulated
write.table(x=downregulated_genes,
            file="expr_downregulated_genes.txt",sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)

8. Show up and down-regulated genes

I have shown the up and down-regulated genes in a volcano plot by coloring them in red and blue, the code is from (Annick Moisan, n.d.)

9. Test Differential expression - heatmap

To test the differential expression, I used the heatmap and it has shown a clear distinction between up and down regulated genes. There is a clear difference between the primary tumour samples and tumoursphere samples.(They are reversed.) The clustering is very obvious to show that differential expression exists.

Coefficient:  samples$cell_typeSphere 

Thresholded over-representation analysis

Are there any gene sets or pathways that are enriched/over-represented or depleted/under-represented in my list? ### Introduction to PART 2: 1. Which method did you choose and why? * I chose to use g:profiler because it shows me the top term names in KEGG, WP, GO and REAC, which is helpful for me when deciding what type of disease it is most likely to be. 2. What annotation data did you use and why? What version of the annotation are you using? * GO biological process: releases/2019-07-01 * KEGG: KEGG FTP Release 2019-09-30 * Reactome: ensembl classes: 2019-10-2 * WikiPathways: 20190910 3. How many genesets were returned with what thresholds? * The threshold for all the queries: 0.05 * 821 gene sets are returned for all the differentially expressed genes. * 60 gene sets are returned for up-regulated genes. * 1333 gene sets are returned for down-regulated genes.

  1. Run the analysis using the up-regulated set of genes, and the down-regulated set of genes separately. How do these results compare to using the whole list (i.e all differentially expressed genes together vs. the up-regulated and down regulated differentially expressed genes separately)?
  • The up-regulated gene sets are mostly cellular processes and metabolic processes.
  • The top terms for down-regulated gene sets are mostly signaling pathways and metabolic processes/
  • When running with both up and down-regulated genes, I found that most of them are dominated by the metabolic and cellular processes (up regulated top terms). Therefore, it convinces me the importance of the up-regulated genes in the cancer. And the result aligns with the paper that states the cancer is of subtype “basal”.
  • Below are my results for each up-regulated, down-regulated, and differentially expressed (both).

1. Up regulated genes

There were no REAC found. I used the gprofiler2’s function to query data and also attached the screenshots that I took on their website since the package does not show the number of gene sets each has found.

2. Down regulated genes

The some analysis is apply to down regulated

3. All differentially expressed genes

Interpretation questions

  1. Do the over-representation results support conclusions or mechanism discussed in the original paper?
  • The paper found 1401 genes being up-regulated with fold change > 2 and FDR < 0.05. I found 1312 which is roughly similar. They also found that ALDH family is up-regulated as well. But I found 3 of them in my upregulated genes. The disease is indicated as 31% of basal-like tumors, 12% (HER2)+ tumors and 10% of luminal tumors, since the top terms of my upregulated genes are metabolic processes, therefore, the result aligns with the paper.
  • The paper did not mention about the down-regulated genes.
  1. Evidence that support and how they support your results.
  • My result #1: ALDH family is found in my up regulated genes. Verification of over-representation of ALDH is an important family in breast cancer by (Vassalli 2019). They consider ALDH family as a biomarker for breast cancer which sugguests that my result (the fact that up-regulated genes contains the ALDH family is verified).
  • My result #2: top terms of the upregulated genes are mostly cellular and metabolic processes. (Vasiliou and Nebert 2005) convinces me that my result from g:profiler matches with the basal subtype. The paper states that mutations in ALDH genes causes metabolism errors, for example, Sjögren - Larsson syndrome, type II hyperprolinaemia and γ-hydroxybutyric aciduria and even cancer and Alzheimer’s disease.

Part 3: non-thresholded + network analysis

The objective of this third assignment is to use the ranked file from A2 and perform non-thresholded analysis with GSEA (Version 4.0.3) (Efron and Tibshirani 2019). Then the result is compared to the result from thresholded analysis in A2. Finally, cytoscape (Version 3.7.2, Java 1.8.0_162 by Oracle Corporation)(Lopes et al. 2010) is used to help to create a visualization of the up and down regulated genes along with annotations from the Bader lab. Post analysis is performed with drugBank datasets from Bader lab as well. Other details such as performing the analysis of cytoscape can be retrieved from my Journal

R Libraries used:

Non-thresholded Gene set Enrichment Analysis

Are there any gene sets or pathways that are ranked surprisingly high or low in my ranked list?

1.Get Bader lab gene sets

  • The code is inspired by lecture notes: non-thresholded analysis unit.
gmt_url = "http://download.baderlab.org/EM_Genesets/current_release/Human/symbol/"
# list all the files on the server
filenames = getURL(gmt_url)
tc = textConnection(filenames)
contents = readLines(tc)
close(tc)
# get the gmt that has all the pathways and does not include terms inferred from
# electronic annotations(IEA) start with gmt file that has pathways only
rx = gregexpr("(?<=<a href=\")(.*.GOBP_AllPathways_no_GO_iea.*.)(.gmt)(?=\">)", contents, 
    perl = TRUE)
gmt_file = unlist(regmatches(contents, rx))
download.file(paste(gmt_url, gmt_file, sep = ""), destfile = dest_gmt_file)

2. Compute ranks

  • I obtained the rank file, computed the ranks and sorted table by ranks. The output file is “expr_RNAseq_ranks.rnk” which is to be loaded into GSEA for further analysis.
  • rank = -log10(p-val)*sign(logFC)
# compute ranks
qlf_output_hits_withgn[,"rank"] <- log(qlf_output_hits_withgn$PValue, base = 10) * sign(qlf_output_hits_withgn$logFC)

# sort table by ranks
qlf_output_hits_withgn <- qlf_output_hits_withgn[order(qlf_output_hits_withgn$rank),]

# write gene name and rank to table
write.table(x=qlf_output_hits_withgn[, c(2, ncol(qlf_output_hits_withgn))],
            file="expr_RNAseq_ranks.rnk",sep = "\t",
            row.names = FALSE,col.names = FALSE,quote = FALSE)
kable(head(qlf_output_hits_withgn), caption = "Expr_RNAseq_ranks", format="html") %>%
  kable_styling(bootstrap_options = "hover")

3. Conduct non-thresholded gene set enrichment analysis

I used the computed ranked set of genes to compute the non-thresholded gene set entichment analysis with GSEA_4.0.3.(Efron and Tibshirani 2019) I loaded the rank file “expr_RNAseq_ranks.rnk” and Bader Lab gene set “human_GOBP_AllPathways_no_GO_iea_March_01_2020_symbol.gmt”. The parameters are permutation = 100, no collapse, max = 200, min = 15. The file obtained is: “A3_part1_non_thres.GseaPreranked.1584469398976”. Here is a screenshot before performing the analysis on GSEA.

4. Summarize enrichment results

My data is divided into “POS” and “NEG” which correspond to up-regulatedand down-regulated genes.

  • For the “POS” group,
    • Humoral immune response is the top term
    • P-val = 0,
    • 9 genes in its leading edge
    • The top gene associated with this geneset is IGKV2D-28.


processing file: A2.Rmd

  |                                                                                                                               
  |                                                                                                                         |   0%
  |                                                                                                                               
  |..                                                                                                                       |   1%
  ordinary text without R code


  |                                                                                                                               
  |...                                                                                                                      |   3%
label: unnamed-chunk-2

  |                                                                                                                               
  |.....                                                                                                                    |   4%
  ordinary text without R code


  |                                                                                                                               
  |......                                                                                                                   |   5%
label: download data (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |........                                                                                                                 |   7%
  ordinary text without R code


  |                                                                                                                               
  |..........                                                                                                               |   8%
label: samples_prefiltered

  |                                                                                                                               
  |...........                                                                                                              |   9%
  ordinary text without R code


  |                                                                                                                               
  |.............                                                                                                            |  11%
label: check GENEID dup (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |...............                                                                                                          |  12%
  ordinary text without R code


  |                                                                                                                               
  |................                                                                                                         |  13%
label: boxplot_prefiltered (with options) 
List of 1
 $ warning: logi FALSE


  |                                                                                                                               
  |..................                                                                                                       |  15%
  ordinary text without R code


  |                                                                                                                               
  |...................                                                                                                      |  16%
label: density_prefiltered

  |                                                                                                                               
  |.....................                                                                                                    |  17%
  ordinary text without R code


  |                                                                                                                               
  |.......................                                                                                                  |  19%
label: MDS_prefiltered

  |                                                                                                                               
  |........................                                                                                                 |  20%
  ordinary text without R code


  |                                                                                                                               
  |..........................                                                                                               |  21%
label: filter

  |                                                                                                                               
  |...........................                                                                                              |  23%
  ordinary text without R code


  |                                                                                                                               
  |.............................                                                                                            |  24%
label: boxplot_filtered (with options) 
List of 1
 $ warning: logi FALSE


  |                                                                                                                               
  |...............................                                                                                          |  25%
  ordinary text without R code


  |                                                                                                                               
  |................................                                                                                         |  27%
label: unnamed-chunk-3

  |                                                                                                                               
  |..................................                                                                                       |  28%
  ordinary text without R code


  |                                                                                                                               
  |...................................                                                                                      |  29%
label: unnamed-chunk-4

  |                                                                                                                               
  |.....................................                                                                                    |  31%
  ordinary text without R code


  |                                                                                                                               
  |.......................................                                                                                  |  32%
label: identifier mapping (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |........................................                                                                                 |  33%
  ordinary text without R code


  |                                                                                                                               
  |..........................................                                                                               |  35%
label: unmapped GENEIDs

  |                                                                                                                               
  |............................................                                                                             |  36%
  ordinary text without R code


  |                                                                                                                               
  |.............................................                                                                            |  37%
label: samples_filtered

  |                                                                                                                               
  |...............................................                                                                          |  39%
  ordinary text without R code


  |                                                                                                                               
  |................................................                                                                         |  40%
label: check SYMBOL dup (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |..................................................                                                                       |  41%
  ordinary text without R code


  |                                                                                                                               
  |....................................................                                                                     |  43%
label: unnamed-chunk-5

  |                                                                                                                               
  |.....................................................                                                                    |  44%
  ordinary text without R code


  |                                                                                                                               
  |.......................................................                                                                  |  45%
label: setup (with options) 
List of 3
 $ results: chr "hide"
 $ include: logi FALSE
 $ echo   : logi FALSE


  |                                                                                                                               
  |........................................................                                                                 |  47%
  ordinary text without R code


  |                                                                                                                               
  |..........................................................                                                               |  48%
label: load norm data

  |                                                                                                                               
  |............................................................                                                             |  49%
  ordinary text without R code


  |                                                                                                                               
  |.............................................................                                                            |  51%
label: boxplot_normalized (with options) 
List of 1
 $ warning: logi FALSE


  |                                                                                                                               
  |...............................................................                                                          |  52%
  ordinary text without R code


  |                                                                                                                               
  |.................................................................                                                        |  53%
label: density_normalized

  |                                                                                                                               
  |..................................................................                                                       |  55%
  ordinary text without R code


  |                                                                                                                               
  |....................................................................                                                     |  56%
label: MDS-1

  |                                                                                                                               
  |.....................................................................                                                    |  57%
  ordinary text without R code


  |                                                                                                                               
  |.......................................................................                                                  |  59%
label: MDS-2

  |                                                                                                                               
  |.........................................................................                                                |  60%
  ordinary text without R code


  |                                                                                                                               
  |..........................................................................                                               |  61%
label: model

  |                                                                                                                               
  |............................................................................                                             |  63%
  ordinary text without R code


  |                                                                                                                               
  |.............................................................................                                            |  64%
label: d object

  |                                                                                                                               
  |...............................................................................                                          |  65%
  ordinary text without R code


  |                                                                                                                               
  |.................................................................................                                        |  67%
label: meanvar

  |                                                                                                                               
  |..................................................................................                                       |  68%
  ordinary text without R code


  |                                                                                                                               
  |....................................................................................                                     |  69%
label: BCV

  |                                                                                                                               
  |......................................................................................                                   |  71%
  ordinary text without R code


  |                                                                                                                               
  |.......................................................................................                                  |  72%
label: threshold and correction (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |.........................................................................................                                |  73%
  ordinary text without R code


  |                                                                                                                               
  |..........................................................................................                               |  75%
label: up and down-regulated (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |............................................................................................                             |  76%
  ordinary text without R code


  |                                                                                                                               
  |..............................................................................................                           |  77%
label: up_volcano

  |                                                                                                                               
  |...............................................................................................                          |  79%
  ordinary text without R code


  |                                                                                                                               
  |.................................................................................................                        |  80%
label: down_volcano

  |                                                                                                                               
  |..................................................................................................                       |  81%
  ordinary text without R code


  |                                                                                                                               
  |....................................................................................................                     |  83%
label: heatmap

  |                                                                                                                               
  |......................................................................................................                   |  84%
  ordinary text without R code


  |                                                                                                                               
  |.......................................................................................................                  |  85%
label: interpretatin questions (with options) 
List of 1
 $ results: chr "hide"


  |                                                                                                                               
  |.........................................................................................................                |  87%
  ordinary text without R code


  |                                                                                                                               
  |..........................................................................................................               |  88%
label: unnamed-chunk-6 (with options) 
List of 1
 $ include: logi FALSE


  |                                                                                                                               
  |............................................................................................................             |  89%
  ordinary text without R code


  |                                                                                                                               
  |..............................................................................................................           |  91%
label: unnamed-chunk-7

  |                                                                                                                               
  |...............................................................................................................          |  92%
  ordinary text without R code


  |                                                                                                                               
  |.................................................................................................................        |  93%
label: unnamed-chunk-8

  |                                                                                                                               
  |...................................................................................................................      |  95%
  ordinary text without R code


  |                                                                                                                               
  |....................................................................................................................     |  96%
label: unnamed-chunk-9 (with options) 
List of 1
 $ echo: logi FALSE


  |                                                                                                                               
  |......................................................................................................................   |  97%
  ordinary text without R code


  |                                                                                                                               
  |.......................................................................................................................  |  99%
label: unnamed-chunk-10 (with options) 
List of 1
 $ echo: logi FALSE


  |                                                                                                                               
  |.........................................................................................................................| 100%
  ordinary text without R code


/Applications/RStudio.app/Contents/MacOS/pandoc/pandoc +RTS -K512m -RTS A2.utf8.md --to html4 --from markdown+autolink_bare_uris+tex_math_single_backslash+smart --output A2.html --email-obfuscation none --self-contained --standalone --section-divs --table-of-contents --toc-depth 1 --template /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rmarkdown/rmd/h/default.html --no-highlight --variable highlightjs=1 --variable 'theme:bootstrap' --include-in-header /var/folders/4h/8ynmzgwd7_z1604r9s1dw5gw0000gn/T//RtmpmewAl1/rmarkdown-str2e1a15f83abd.html --mathjax --variable 'mathjax-url:https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' --lua-filter /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rmarkdown/rmd/lua/pagebreak.lua --lua-filter /Library/Frameworks/R.framework/Versions/3.6/Resources/library/rmarkdown/rmd/lua/latex-div.lua --variable code_folding=show --variable source_embed=A2.Rmd --include-after-body /var/folders/4h/8ynmzgwd7_z1604r9s1dw5gw0000gn/T//RtmpmewAl1/file2e1a5bd8598f.html --variable code_menu=1 --variable kable-scroll=1 --filter /Applications/RStudio.app/Contents/MacOS/pandoc/pandoc-citeproc 
Down-regulated_top_terms
NAME SIZE ES NES NOM.p.val FDR.q.val FWER.p.val RANK.AT.MAX LEADING.EDGE
TGF_BETA_RECEPTOR%IOB%TGF_BETA_RECEPTOR 185 -0.2044902 NA NA 1 0 1836 tags=15%, list=9%, signal=16%
HALLMARK_ADIPOGENESIS%MSIGDB_C2%HALLMARK_ADIPOGENESIS 193 -0.3041408 NA NA 1 0 2169 tags=23%, list=11%, signal=26%
HALLMARK_OXIDATIVE_PHOSPHORYLATION%MSIGDB_C2%HALLMARK_OXIDATIVE_PHOSPHORYLATION 197 -0.6852279 NA NA 1 0 2021 tags=39%, list=10%, signal=43%
HALLMARK_P53_PATHWAY%MSIGDB_C2%HALLMARK_P53_PATHWAY 195 -0.2911640 NA NA 1 0 2716 tags=24%, list=14%, signal=28%
TRANSPORT TO THE GOLGI AND SUBSEQUENT MODIFICATION%REACTOME DATABASE ID RELEASE 71%948021 155 -0.1743973 NA NA 1 0 3435 tags=24%, list=17%, signal=29%
MITOTIC ANAPHASE%REACTOME DATABASE ID RELEASE 71%68882 173 -0.4131416 NA NA 1 0 3058 tags=32%, list=15%, signal=37%
  • In the “NEG” group,
    • TGF beta receptor is the top term
    • P-val = 0
    • 185 genes in its leading edge
    • The top gene associated with is PRKCB.

5. Compare to the results from thresholded analysis

I used g:profiler in A2 to conduct thresholded analysis. The result showed that both the up-regulated and the down-regulated genes have metabolic terms associated. Whereas using the non-thresholded methods, immune response seems to be associated with up-regulated genes. Beta-receptor seems to be associated with the down-regulated group which is the same as the result from g:profiler. Both thresholded and non-thresholded over-representation analysis shows that the disease is associated with immune response and metabolic malfunctions. Such result is consistent with the result from the paper, and I have found some of the evidences from the other papers in A2, showing that breast cancer is associated with these top terms.

Visualize Gene set Enrichment Analysis

1. Create an enrichment map

  • The following visualization is conducted using Cytoscape (Lopes et al. 2010)
  • The parameters I used when creating the enrichment map: FDR was set to 0.01, others are kept as default.
  • Basic information: there are 456 nodes and 5087 edges in the resulting map.
  • Here is a screenshot that gives information about the creation of the enrichment map.

2. Annotate the enrichment map

I defined the main biological themes by using clicking on “auto annotate” -> “annotate”. The system created circles around each cluster which corresponds to the most frequent node lavles in the cluster. Here is a screenshot of the overview.

3. Manually edit the network

  • I made sure that there is no overlap between the labels and the nodes. I also oragnized them to make the interactions clearer. The legend is obtained from Bader lab’s website.
  • I did not screenshot the network since it is the same as the resulting graph that also contains the two drugs I picked. The screenshot can be found in the section: " Post analysis - Drug Bank".

4. Collapse to a theme network

  • Generally, the major themes I found after collapsing the annotated network: immune responses, cell proliferation, tageting, and signaling.There seems to be no novel pathways.
  • Here is an overview of the collapsed graph.

5. Interpretation of the annotated network

  • Terms on the left are up-regulated genes and terms on the right are down-regulated genes. The lines shows us the interactions between each most frequent terms.
  • On the left side, we can see that the term that has the most interactions with the rest is “response immune immunoglobulin”. It is connected to terms like “lymphocyte proliferation”, “differentiation”, “negative cell regulation”, “signaling”, etc. Elevated level immunoglobulin antibodies is frequently observed in cancers of epithelial origin, including carcinomas of breast, colon, and liver.(Qiu et al. 2003) Therefore, it justifies the reason why this term is up-regulated.
  • On the right side, we notice the main term is “APC dedegradation” (with the most genes). Antigen presenting cells (APCs) are immune cells that specialize in presenting an antigen to a T-cell. APC protein acts as a tumor suppressor, therefore, the degradation of APC means that the suppressor is no longer fully supplied which can not stop the disease from expanding. Other terms are related to cell * transport, etc.
  • In conclusion, those terms are predicted by the g:profiler in A2 even if they don’t have the exact same names. Therefore, we can conclude that the disease is mostly due to immune response malfunction, which then leads to problems in cell metabolism in various ways.

6. Post analysis - Drug Bank

The reason why I choose to do the post analysis with drugs is because the paper mentioned about finding a target for a drug. The drug is Pacritinib. However, this drug is not annotated, and thus not stored in the Bader Lab file. Therefore, I chose the top drug (Abciximab) (Law et al. 2014) from Bader lab approved drugs file. The paper also mentioned that they use Gemcitabine to treat breast cancer if the disease does not expand further.

  • Parameters: Mann Whiteney(One-sided greater): since I do not care whether it targets the up-regulated or down-regulated genes.

  • The resulting graph shows that there are no connection for Gemcitabine with any pathways, and a lot of up-regulated genes are targeted by Abciximab. The terms that are targeted are mostly the up-regulated genes, such as “response immune immunoglobin”, to reduce the elevated level of the antibody. It also reduces the level of other cell metabolic terms that are in the same pathway as the “response immune immunoglobin” (discussed in the section above). The main function of this drug is to reduce antibodies, and other over-produced molecules, but not elevating the weak terms (the down-regulated genes).

  • The only thing not expected is that Gemcitabine does not target the term “cell proliferation positive” which is what the main object of Gemcitabine. Gemcitabine is a drug that kills the fast-growing cells. Therefore, it is not expected to see that this drug does nothing in this disease pathway.

  • It might be hard to see the Gemcitabine, it is right beside Abciximab,.

References

Annick Moisan, Nathalie Villa-Vialaneix, Ignacio Gonzales. n.d. “Practical Statistical Analysis of Rna-Seq Data - edgeR - Tomato Data.”

Efron, Brad, and R. Tibshirani. 2019. GSA: Gene Set Analysis. https://CRAN.R-project.org/package=GSA.

Goh, Jian Yuan, Min Feng, Wenyu Wang, Gokce Oguz, Siti Maryam JM Yatim, Puay Leng Lee, Yi Bao, et al. 2017. “Chromosome 1q21.3 Amplification Is a Trackable Biomarker and Actionable Target for Breast Cancer Recurrence.” Nature Medicine 23 (11). Nature Publishing Group: 1319.

Gu, Zuguang, Roland Eils, and Matthias Schlesner. 2016. “Complex Heatmaps Reveal Patterns and Correlations in Multidimensional Genomic Data.” Bioinformatics.

Gu, Zuguang, Lei Gu, Roland Eils, Matthias Schlesner, and Benedikt Brors. 2014. “Circlize Implements and Enhances Circular Visualization in R.” Bioinformatics 30 (19): 2811–2.

Kolberg, Liis, and Uku Raudvere. 2019. Gprofiler2: Interface to the ’G:Profiler’ Toolset. https://CRAN.R-project.org/package=gprofiler2.

Law, Vivian, Craig Knox, Yannick Djoumbou, Tim Jewison, An Chi Guo, Yifeng Liu, Adam Maciejewski, et al. 2014. “DrugBank 4.0: Shedding New Light on Drug Metabolism.” Nucleic Acids Research 42 (D1). Oxford University Press: D1091–D1097.

Lopes, Christian T, Max Franz, Farzana Kazi, Sylva L Donaldson, Quaid Morris, and Gary D Bader. 2010. “Cytoscape Web: An Interactive Web-Based Network Browser.” Bioinformatics 26 (18). Oxford University Press: 2347–8.

Qiu, Xiaoyan, Xiaohui Zhu, Liang Zhang, Yuntao Mao, Jian Zhang, Peng Hao, Guohui Li, et al. 2003. “Human Epithelial Cancers Secrete Immunoglobulin G with Unidentified Specificity to Promote Growth and Survival of Tumor Cells.” Cancer Research 63 (19). AACR: 6488–95.

Rainer, Johannes. 2017. EnsDb.Hsapiens.v75: Ensembl Based Annotation Package.

Ritchie, Matthew E, Belinda Phipson, Di Wu, Yifang Hu, Charity W Law, Wei Shi, and Gordon K Smyth. 2015. “limma Powers Differential Expression Analyses for RNA-Sequencing and Microarray Studies.” Nucleic Acids Research 43 (7): e47. https://doi.org/10.1093/nar/gkv007.

Temple Lang, Duncan. 2020. RCurl: General Network (Http/Ftp/...) Client Interface for R. https://CRAN.R-project.org/package=RCurl.

Vasiliou, Vasilis, and Daniel W Nebert. 2005. “Analysis and Update of the Human Aldehyde Dehydrogenase (Aldh) Gene Family.” Human Genomics 2 (2). BioMed Central: 138.

Vassalli, Giuseppe. 2019. “Aldehyde Dehydrogenases: Not Just Markers, but Functional Regulators of Stem Cells.” Stem Cells International 2019. Hindawi.

Xie, Yihui. 2020. Knitr: A General-Purpose Package for Dynamic Report Generation in R. https://yihui.org/knitr/.

Zhu, Hao. 2019. KableExtra: Construct Complex Table with ’Kable’ and Pipe Syntax. https://CRAN.R-project.org/package=kableExtra.

LS0tCnRpdGxlOiAiUk5Bc2VxIGFuYWx5c2lzIHdvcmtmbG93IgphdXRob3I6ICJZaW5pbmcgRGluZyAoMTAwMzg5ODQ0NikiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwpiaWJsaW9ncmFwaHk6IEEyLmJpYgotLS0KCiMgUGFydCAxOiBjbGVhbiBhbmQgbm9ybWFsaXplIGRhdGEKTXkgZGF0YSBpcyBmcm9tIEdTRTg0MDU0IFtAZ29oMjAxN2Nocm9tb3NvbWVdLiBUaXRsZTogVHJhbnNjcmlwdG9tZSBwcm9maWxpbmcgb2YgRVIrIGJyZWFzdCBjYW5jZXIgcHJpbWFyeSB0dW1vciBhbmQgaXRzIHR1bW9yc3BoZXJlIGRlcml2YXRpdmUuCk92ZXJ2aWV3IG9mIHRoZSBkYXRhc2V0OiAxMiBFUisgcHJpbWFyeSB0dW1vciBhbmQgdHVtb3JzcGhlcmVzLiBUaGUgb2JqZWN0aXZlIG9mIHRoZSBhdXRob3JzIHdlcmUgdG8gZmluZCBnZW5lcyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2VlbiB0aGVzZSB0d28gZ3JvdXBzLgoKYGBge3Igc2V0dXAsIHJlc3VsdHM9ImhpZGUiLCBpbmNsdWRlID0gRkFMU0UsZWNobz1GQUxTRX0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgibGltbWEiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgibGltbWEiKQoKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZWRnZVIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZWRnZVIiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJFbnNEYi5Ic2FwaWVucy52NzUiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiRW5zRGIuSHNhcGllbnMudjc1IikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgia25pdHIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgia25pdHIiKQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkdFT3F1ZXJ5IiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkdFT3F1ZXJ5IikKbGlicmFyeShsaW1tYSkKbGlicmFyeShlZGdlUikKbGlicmFyeShFbnNEYi5Ic2FwaWVucy52NzUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoR0VPcXVlcnkpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMjIERvd25sb2FkIGRhdGEKYGBge3IgZG93bmxvYWQgZGF0YX0KIyBEb3dubG9hZCBkYXRhc2V0CmRhdGFmaWxlIDwtICJHU0U4NDA1NF9SYXdjb3VudF8xMnBhdGllbnRFUi50eHQuZ3oiCmlmICghZmlsZS5leGlzdHMoZGF0YWZpbGUpKSB7CiAgICBkYXRhZmlsZSA8LSBHRU9xdWVyeTo6Z2V0R0VPU3VwcEZpbGVzKCdHU0U4NDA1NCcsIG1ha2VEaXJlY3RvcnkgPSBGQUxTRSkKfQpleHByIDwtIHJlYWQuZGVsaW0oZGF0YWZpbGUsaGVhZGVyPVRSVUUsY2hlY2submFtZXM9RkFMU0UpCiMgZGltKGV4cHIpICMgNTcyNjggICAgMjUKCiMgRGlzcGxheSByYXdjb3VudCBmaWxlCmthYmxlKGV4cHJbMTo1LDE6MTBdLCBmb3JtYXQgPSAiaHRtbCIpCmBgYAoKIyMgQ2hlY2sgR0VORUlEIGR1cGxpY2F0aW9ucwpJdCBpcyBpbXBvcnRhbnQgdG8gY2hlY2sgZm9yIEdFTkUgSUQgZHVwbGljYXRpb25zIGJlY2F1c2Ugd2UgYXJlIGdvaW5nIHRvIG1hcCB0aGVtIHRvIGhnMTkuIFdlIG5lZWQgdG8gcHJldmVudCBvbmUgdG8gbXVsdGlwbGUgb3IgbXVsdGlwbGUgdG8gb25lIHNjZW5hcmlvcy4gSXQgdHVybnMgb3V0IHdlIGRvIG5vdCBoYXZlIGR1cGxpY2F0ZWQgR0VORUlEcy4KYGBge3IgY2hlY2sgR0VORUlEIGR1cCwgcmVzdWx0cz0iaGlkZSJ9CiMgTk8gZHVwbGljYXRpb25zIQpzdW1tYXJpemVkX2dlbmVfY291bnRzX2ZpbHRlcmVkIDwtIHNvcnQodGFibGUoZXhwclssMV0pLGRlY3JlYXNpbmcgPSBUUlVFKQpsZW5ndGgoc3VtbWFyaXplZF9nZW5lX2NvdW50c19maWx0ZXJlZFt3aGljaChzdW1tYXJpemVkX2dlbmVfY291bnRzX2ZpbHRlcmVkPjEpXSkgIyAwCmBgYAojIyBFeHBsb3JlIApgYGB7ciBib3hwbG90X3ByZWZpbHRlcmVkLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQojIyBwcmVmaWx0ZXJlZCBjb3VudHMKZGF0YTJwbG90IDwtIGxvZzIoY3BtKGV4cHJbLDI6bmNvbChleHByKV0pKQpib3hwbG90KGRhdGEycGxvdCwgeGxhYiA9ICJTYW1wbGVzIiwgeWxhYiA9ICJsb2cyIENQTSIsIAogICAgICAgIGxhcyA9IDIsIGNleCA9IDAuNSwgY2V4LmxhYiA9IDAuNSwKICAgICAgICBjZXguYXhpcyA9IDAuNSwgbWFpbiA9ICJwcmUtZmlsdGVyZWQgUk5BU2VxIFNhbXBsZXMiKQojZHJhdyB0aGUgbWVkaWFuIG9uIGVhY2ggYm94IHBsb3QKYWJsaW5lKGggPSBtZWRpYW4oYXBwbHkoZGF0YTJwbG90LCAyLCBtZWRpYW4pKSwgY29sID0gImdyZWVuIiwgbHdkID0gMC42LCBsdHkgPSAiZGFzaGVkIikKYGBgCgpgYGB7ciBkZW5zaXR5X3ByZWZpbHRlcmVkLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb3VudHNfZGVuc2l0eSA8LSBhcHBseShsb2cyKGV4cHJbLDI6bmNvbChleHByKV0pLCAyLCBkZW5zaXR5KQogICNjYWxjdWxhdGUgdGhlIGxpbWl0cyBhY3Jvc3MgYWxsIHRoZSBzYW1wbGVzCiAgICB4bGltIDwtIDA7IHlsaW0gPC0gMAogICAgZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgewogICAgICB4bGltIDwtIHJhbmdlKGMoeGxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR4KSk7IAogICAgICB5bGltIDwtIHJhbmdlKGMoeWxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR5KSkKICAgIH0KICAgIGNvbHMgPC0gcmFpbmJvdyhsZW5ndGgoY291bnRzX2RlbnNpdHkpKQogICAgbHR5cyA8LSByZXAoMSwgbGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKICAgICNwbG90IHRoZSBmaXJzdCBkZW5zaXR5IHBsb3QgdG8gaW5pdGlhbGl6ZSB0aGUgcGxvdAogICAgcGxvdChjb3VudHNfZGVuc2l0eVtbMV1dLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgdHlwZT0ibiIsIAogICAgICAgICB5bGFiPSJTbW9vdGhpbmcgZGVuc2l0eSBvZiBsb2cyLUNQTSIsY2V4LmxhYiA9IDAuODUsIAogICAgICAgICBtYWluID0gIlByZS1maWx0ZXJlZCBEZW5zaXR5IGRpc3RyaWJ1dGlvbiIpCiAgICAjcGxvdCBlYWNoIGxpbmUKICAgIGZvciAoaSBpbiAxOmxlbmd0aChjb3VudHNfZGVuc2l0eSkpIGxpbmVzKGNvdW50c19kZW5zaXR5W1tpXV0sIGNvbD1jb2xzW2ldLCBsdHk9bHR5c1tpXSkKICAgICNjcmVhdGUgbGVnZW5kCiAgICBsZWdlbmQoInRvcHJpZ2h0IiwgY29sbmFtZXMoZGF0YTJwbG90KSwgIAogICAgICAgICAgIGNvbD1jb2xzLCBsdHk9bHR5cywgY2V4PTAuNzUsIAogICAgICAgICAgIGJvcmRlciA9ImJsdWUiLCAgdGV4dC5jb2wgPSAiZ3JlZW40IiwgCiAgICAgICAgICAgbWVyZ2UgPSBUUlVFLCBiZyA9ICJncmF5OTAiKQpgYGAKCmBgYHtyIE1EU19wcmVmaWx0ZXJlZCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyMgcHJlZmlsdGVyZWQgTURTIHBsb3QKcGxvdE1EUyhkLCBsYWJlbHM9cm93bmFtZXMoc2FtcGxlcyksCiAgICAgICAgY29sID0gYygiZGFya2dyZWVuIiwiYmx1ZSIpW2ZhY3RvcihzYW1wbGVzJGNlbGxfdHlwZSldLCAKICAgICAgICBtYWluID0gIlByZS1maWx0ZXJlZCBNRFMgcGxvdCIpCmBgYAoKIyMgRmlsdGVyIG91dCBsb3cgY291bnRzClRoZSBvYmplY3RpdmUgaXMgdG8gcmVtb3ZlIHRoZSBvbmVzIHdpdGggbG93IGNvdW50cy4KV2h5PyBGaWx0ZXIgd2Vha2x5IGV4cHJlc3NlZCBhbmQgbm9uaW5mb3JtYXRpdmUgKGUuZy4sIG5vbi1hbGlnbmVkKSBmZWF0dXJlcy4KSG93PyBXZSB0cmFuc2xhdGUgb3V0IGNvdW50cyBpbnRvIGNvdW50cyBwZXIgbWlsbGlvbiBjcG0oKSxyZW1vdmUgZmVhdHVyZXMgd2l0aG91dCBhdCBsZWFzdCAxIHJlYWQgcGVyIG1pbGxpb24gaW4gbiBvZiB0aGUgc2FtcGxlcywgd2hlcmUgbiBpcyB0aGUgc2l6ZSBvZiB0aGUgc21hbGxlc3QgZ3JvdXAgb2YgcmVwbGljYXRlcwoKYGBge3IgZmlsdGVyfQojIHRyYW5zbGF0ZSBvdXQgY291bnRzIGludG8gY291bnRzIHBlciBtaWxsaW9uCmNwbXMgPSBjcG0oZXhwclssMjoyNV0pCnJvd25hbWVzKGNwbXMpIDwtIGV4cHJbLDFdCiMgZ2V0IHJpZCBvZiBsb3cgY291bnRzCmtlZXAgPSByb3dTdW1zKGNwbXMgPiAxKSA+PSAzCmV4cHJfZmlsdGVyZWQgPC0gZXhwcltrZWVwLF0Kb3V0bGllcnNfcmVtb3ZlZCA8LSBucm93KGV4cHIpIC0gbnJvdyhleHByX2ZpbHRlcmVkKSAjIDM3Mzk1CiMgZGltKGV4cHJfZmlsdGVyZWQpICMgMTk4NzMgICAgMjUKCiMgRGlzcGxheSByYXdjb3VudCBmaWxlCmthYmxlKGV4cHJfZmlsdGVyZWRbMTo1LDE6MTBdLCBmb3JtYXQgPSAiaHRtbCIpCmBgYAojIyBFeHBsb3JlOiBmaWx0ZXJlZApgYGB7ciBib3hwbG90X2ZpbHRlcmVkLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkYXRhMnBsb3QgPC0gbG9nMihjcG0oZXhwcl9maWx0ZXJlZFssMzpuY29sKGV4cHJfZmlsdGVyZWQpXSkpCmJveHBsb3QoZGF0YTJwbG90LCB4bGFiID0gIlNhbXBsZXMiLCB5bGFiID0gImxvZzIgQ1BNIiwgCiAgICAgICAgbGFzID0gMiwgY2V4ID0gMC41LCBjZXgubGFiID0gMC41LAogICAgICAgIGNleC5heGlzID0gMC41LCBtYWluID0gIkZpbHRlcmVkIFJOQVNlcSBTYW1wbGVzIikKI2RyYXcgdGhlIG1lZGlhbiBvbiBlYWNoIGJveCBwbG90CmFibGluZShoID0gbWVkaWFuKGFwcGx5KGRhdGEycGxvdCwgMiwgbWVkaWFuKSksIGNvbCA9ICJncmVlbiIsIGx3ZCA9IDAuNiwgbHR5ID0gImRhc2hlZCIpCmBgYAoKYGBge3IgZGVuc2l0eSBhZnRlciBmaWx0cmF0aW9uLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpjb3VudHNfZGVuc2l0eSA8LSBhcHBseShsb2cyKGV4cHJfZmlsdGVyZWRbLDM6bmNvbChleHByX2ZpbHRlcmVkKV0pLCAyLCBkZW5zaXR5KQogICNjYWxjdWxhdGUgdGhlIGxpbWl0cyBhY3Jvc3MgYWxsIHRoZSBzYW1wbGVzCiAgICB4bGltIDwtIDA7IHlsaW0gPC0gMAogICAgZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgewogICAgICB4bGltIDwtIHJhbmdlKGMoeGxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR4KSk7IAogICAgICB5bGltIDwtIHJhbmdlKGMoeWxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR5KSkKICAgIH0KICAgIGNvbHMgPC0gcmFpbmJvdyhsZW5ndGgoY291bnRzX2RlbnNpdHkpKQogICAgbHR5cyA8LSByZXAoMSwgbGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKICAgICNwbG90IHRoZSBmaXJzdCBkZW5zaXR5IHBsb3QgdG8gaW5pdGlhbGl6ZSB0aGUgcGxvdAogICAgcGxvdChjb3VudHNfZGVuc2l0eVtbMV1dLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgdHlwZT0ibiIsIAogICAgICAgICB5bGFiPSJTbW9vdGhpbmcgZGVuc2l0eSBvZiBsb2cyLUNQTSIsY2V4LmxhYiA9IDAuODUsIAogICAgICAgICBtYWluID0gIkZpbHRlcmVkIERlbnNpdHkgZGlzdHJpYnV0aW9uIikKICAgICNwbG90IGVhY2ggbGluZQogICAgZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgbGluZXMoY291bnRzX2RlbnNpdHlbW2ldXSwgY29sPWNvbHNbaV0sIGx0eT1sdHlzW2ldKQogICAgI2NyZWF0ZSBsZWdlbmQKICAgIGxlZ2VuZCgidG9wcmlnaHQiLCBjb2xuYW1lcyhkYXRhMnBsb3QpLCAgCiAgICAgICAgICAgY29sPWNvbHMsIGx0eT1sdHlzLCBjZXg9MC43NSwgCiAgICAgICAgICAgYm9yZGVyID0iYmx1ZSIsICB0ZXh0LmNvbCA9ICJncmVlbjQiLCAKICAgICAgICAgICBtZXJnZSA9IFRSVUUsIGJnID0gImdyYXk5MCIpCmBgYAoKYGBge3IgbWRzIGFmdGVyIGZpbHRyYXRpb24sIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIEZpbHRlcmVkIE1EUyBwbG90CnBsb3RNRFMoZCwgbGFiZWxzPXJvd25hbWVzKHNhbXBsZXNfZmlsdGVyZWQpLAogICAgICAgIGNvbCA9IGMoImRhcmtncmVlbiIsImJsdWUiKVtmYWN0b3Ioc2FtcGxlc19maWx0ZXJlZCRjZWxsX3R5cGUpXSkKYGBgCiMjIElkZW50aWZpZXIgbWFwcGluZwpgYGB7ciBpZGVudGlmaWVyIG1hcHBpbmcsIHJlc3VsdHM9J2hpZGUnfQplbnNlbWJsX2lkIDwtIGFzLmNoYXJhY3RlcihleHByX2ZpbHRlcmVkWywxXSkKCkVuc0RiX3RyYW5zX2Vuc2VtYmw8LSBlbnNlbWJsZGI6OnNlbGVjdChFbnNEYi5Ic2FwaWVucy52NzUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cyA9IGVuc2VtYmxfaWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnM9IlNZTUJPTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5dHlwZT0iR0VORUlEIikKCmRhdGEuZnJhbWUoRW5zRGJfdHJhbnNfZW5zZW1ibCkKIyBucm93KEVuc0RiX3RyYW5zX2Vuc2VtYmwpICMgMTk4NTYgaWRzIG1hcHBlZApgYGAKIyMgVW5tYXBwZWQgR0VORUlEcwpUaGUgMTcgdW5tYXBwZWQgZ2VuZSBpZHMgYXJlIGFjdHVhbGx5IGR1cGxpY2F0ZXMuIFRoZSByZWFzb24gd2h5IHRoZSBwcmV2aW91cyBjaGVjayBkaWQgbm90IGNhdGNoIHRoZW0gd2FzIGJlY2F1c2UgaWYgd2UgY2hhbmdlIHRoZSAiUiIgdG8gIjAiLCB0aGV5IGNhbiBiZSBkZXRlY3RlZC4gKFRoZXkgYXJlIGV4YWN0bHkgc2FtZSwgZXhjZXB0IGxvY2F0aW5nIG9uIHRoZSBZIGNocm9tb3NvbWUpLiBTbyBoZXJlIEkgYW0ganVzdCBnb2luZyB0byByZW1vdmUgdGhlbS4KYGBge3IgdW5tYXBwZWQgR0VORUlEc30KdGVzdF9maWx0ZXJlZCA8LSBleHByX2ZpbHRlcmVkCgojIG1lcmdlIG1hcHBlZCBkZiBFbnNEYl90cmFuc19lbnNlbWJsIGFuZCB1bm1hcHBlZCBkZiB0ZXN0X2ZpbHRlcmVkCnRlc3RfZmlsdGVyZWQgPC0gbWVyZ2UoRW5zRGJfdHJhbnNfZW5zZW1ibCwKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0X2ZpbHRlcmVkLCAKICAgICAgICAgICAgICAgICAgICAgICBieS54PTEsIGJ5Lnk9MSwgYWxsLnk9VFJVRSApCiMgbnJvdyh0ZXN0X2ZpbHRlcmVkKSAjIDE5ODczCmthYmxlKHRlc3RfZmlsdGVyZWRbMTo1LCAxOjVdLCBmb3JtYXQgPSAiaHRtbCIpICAKCiMgZHVwbGljYXRlZCBlbnNlbWJsIGlkCmR1cF9nZW5lX2lkIDwtICh0ZXN0X2ZpbHRlcmVkJEdFTkVJRFt3aGljaChpcy5uYSh0ZXN0X2ZpbHRlcmVkJFNZTUJPTCkpXSkKIyBsZW5ndGgoZHVwX2dlbmVfaWQpICMgMTcKCiMgZGlzcGxheSB0aGUgdW5tYXBwZWQgZW5zZW1ibCBpZHMKa2FibGUodGVzdF9maWx0ZXJlZFt3aGljaChpcy5uYSh0ZXN0X2ZpbHRlcmVkJFNZTUJPTCkpLF1bLDE6NV0sIGZvcm1hdCA9ICJodG1sIikKCiMgU2luY2UgSSBoYXZlIHByb3ZlZCBpdCwgSSB3aWxsIGRpcmVjdGx5IGV4Y2x1ZGUgdGhlbSBmcm9tIGV4cHJfZmlsdGVyZWQKdGVzdF9maWx0ZXJlZCA8LSB0ZXN0X2ZpbHRlcmVkWy13aGljaChpcy5uYSh0ZXN0X2ZpbHRlcmVkJFNZTUJPTCkpLF0KIyBucm93KHRlc3RfZmlsdGVyZWQpICMgMTk4NTYKZXhwcl9maWx0ZXJlZCA8LSB0ZXN0X2ZpbHRlcmVkCiMgbnJvdyhleHByX2ZpbHRlcmVkKSAjIDE5ODU2CnJvd25hbWVzKGV4cHJfZmlsdGVyZWQpIDwtIDE6bnJvdyhleHByX2ZpbHRlcmVkKQojIChudW1fZHVwX2lkIDwtIGxlbmd0aChleHByX2ZpbHRlcmVkJEdFTkVJRFt3aGljaChkdXBsaWNhdGVkKGV4cHJfZmlsdGVyZWQkR0VORUlEKSldKSkgIyAwIGR1cGxpY2F0ZWQKCiMgYWxsKEVuc0RiX3RyYW5zX2Vuc2VtYmwkR0VORUlEID09IGV4cHJfZmlsdGVyZWQkR0VORUlEKSAjIFRSVUUKIyBhbGwoRW5zRGJfdHJhbnNfZW5zZW1ibCRTWU1CT0wgPT0gZXhwcl9maWx0ZXJlZCRTWU1CT0wpICMgVFJVRQpgYGAKCiMjIEdyb3VwIHNhbXBsZXMKQ2F0ZWdvcml6ZSB0aGUgc2FtcGxlcyBiYXNlZCBvbiB0aGVpciBjZWxsIHR5cGVzLgpgYGB7ciBzYW1wbGVzX2ZpbHRlcmVkfQpzYW1wbGVzX2ZpbHRlcmVkIDwtIGRhdGEuZnJhbWUoInBhdGllbnRzIiA9IDE6MjQsImNlbGxfdHlwZSI9MToyNCkKcm93bmFtZXMoc2FtcGxlc19maWx0ZXJlZCkgPC0gY29sbmFtZXMoZXhwcl9maWx0ZXJlZClbMzpuY29sKGV4cHJfZmlsdGVyZWQpXQoKZm9yIChpIGluIDE6MTIpewogIHNhbXBsZXNfZmlsdGVyZWQkY2VsbF90eXBlW2ldID0gIlByaW1hcnkgVHVtb3VyIgogIHNhbXBsZXNfZmlsdGVyZWQkcGF0aWVudHNbaV0gPSBpCiAgc2FtcGxlc19maWx0ZXJlZCRwYXRpZW50c1tpICsgMTJdID0gaQp9Cgpmb3IgKGogaW4gMTM6MjQpewogIHNhbXBsZXNfZmlsdGVyZWQkY2VsbF90eXBlW2pdID0gIlNwaGVyZSIKfQoKIyBBZGQgY2VsbF90eXBlIHRvIHNhbXBsZSBuYW1lcwpjZWxsX3R5cGVfaW5kaWNhdG9yIDwtIHN1YnN0cmluZyhzYW1wbGVzX2ZpbHRlcmVkJGNlbGxfdHlwZSwxLDEpICMgZmlyc3QgY2hhcmFjdGVycyBvZiBjZWxsIHR5cGVzCnJvd25hbWVzKHNhbXBsZXNfZmlsdGVyZWQpIDwtIHBhc3RlMChyb3duYW1lcyhzYW1wbGVzX2ZpbHRlcmVkKSwgc2VwPSJfIiwgY2VsbF90eXBlX2luZGljYXRvcikKCiMgZGlzcGxheSBncm91cGVkIGZvcm1hdAprYWJsZShzYW1wbGVzX2ZpbHRlcmVkLCBmb3JtYXQgPSAiaHRtbCIpICAKYGBgCgojIyBHRU5FIG5hbWUgZHVwbGljYXRpb24KICAqIEluIEExIEkgc2hvd2VkIHRoYXQgdGhlcmUgYXJlIDQxIGR1cGxpY2F0aW9ucyAoMTIgdW5pcXVlIG9uZXMpLCBSdXRoIHN1Z2d1ZXN0ZWQgdG8ga2VlcCB0aGVtIGJlY2F1c2UgaXQgaXMgYSB2ZXJ5IHNtYWxsIHBlcmNlbnQuIEJ1dCBJIGZpbmQgdGhlIE1EUyBwbG90IChjb2xvciBieSBzYW1wbGUpIHdpbGwgYmUgYSBsaXR0bGUgbWVzc3kgaWYgSSBrZWVwIHRoZW0uIEJ1dCBjb2xvciBieSBwYXRpZW50IHRvdGFseSB3b3Jrcy4KYGBge3IgY2hlY2sgU1lNQk9MIGR1cCwgcmVzdWx0cz0naGlkZSd9CmR1cF9nZW5lX25hbWUgPC0gc29ydCh0YWJsZShleHByX2ZpbHRlcmVkJFNZTUJPTCksZGVjcmVhc2luZyA9IFRSVUUpCmxlbmd0aChkdXBfZ2VuZV9uYW1lW3doaWNoKGR1cF9nZW5lX25hbWU+MSldKSAjIDEyCmBgYAoKIyMgQXBwbHkgbm9ybWFsaXphdGlvbiBvbiBleHByX2ZpbHRlcmVkCmBgYHtyfQojIG5lZWQgYSBtYXRyaXggd2l0aCBvbmx5IHZhbHVlcwpmaWx0ZXJlZF9kYXRhX21hdHJpeCA8LSBhcy5tYXRyaXgoZXhwcl9maWx0ZXJlZFssMzpuY29sKGV4cHJfZmlsdGVyZWQpXSkKCiMgUm93bmFtZXMgYmUgdGhlIGVuc2VtYmwgaWQKcm93bmFtZXMoZmlsdGVyZWRfZGF0YV9tYXRyaXgpIDwtIGV4cHJfZmlsdGVyZWQkR0VORUlECgojIERFR0xpc3Qgb2JqZWN0CmQgPC0gREdFTGlzdChjb3VudHM9ZmlsdGVyZWRfZGF0YV9tYXRyaXgsIGdyb3VwPXNhbXBsZXNfZmlsdGVyZWQkY2VsbF90eXBlKQoKIyBOb3JtYWxpemF0aW9uCmQgPC0gY2FsY05vcm1GYWN0b3JzKGQpCgojIGdldCBub3JtYWxpemVkIGNvdW50cwpub3JtYWxpemVkX2NvdW50cyA8LSBjcG0oZCkKCm5vcm1hbGl6ZWRfY291bnRzIDwtIGRhdGEuZnJhbWUobm9ybWFsaXplZF9jb3VudHMpCm5vcm1hbGl6ZWRfY291bnRzIDwtIGNiaW5kKCJTWU1CT0wiID0gZXhwcl9maWx0ZXJlZCRTWU1CT0wsIG5vcm1hbGl6ZWRfY291bnRzKQpub3JtYWxpemVkX2NvdW50cyA8LSBjYmluZCgiR0VORUlEIiA9IGV4cHJfZmlsdGVyZWQkR0VORUlELCBub3JtYWxpemVkX2NvdW50cykKIyBucm93KG5vcm1hbGl6ZWRfY291bnRzKSAjIDE5ODU2CiMgSFVHTyBzeW1ib2xzIGFzIHJvd25hbWVzIG9mIHRoZSBkYXRhZnJhbWUKa2FibGUobm9ybWFsaXplZF9jb3VudHNbMTo1LDE6NV0sIGZvcm1hdCA9ICJodG1sIikKIyBBbGwgcm93cyBoYXZlIGEgdW5pcXVlIEhVR08gc3ltYm9scywgCiMgc3VtKGR1cGxpY2F0ZWQocm93bmFtZXMobm9ybWFsaXplZF9jb3VudHMpKSkgIyAwCndyaXRlLnRhYmxlKG5vcm1hbGl6ZWRfY291bnRzLCBmaWxlPSJHU0U4NDA1NF9ub3JtYWxpemVkX2NvdW50LnR4dCIpCmBgYAoKIyBQYXJ0IDI6IERFICsgdGhyZXNob2xkZWQgb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcwoqIExpYnJhcmllcyB1c2VkIGluIEEyOgogICogTGltbWFbQGxpbW1hXQogICogRW5zZW1ibCBIc2FwaWVucyB2NzVbQEVuc0RiLkhzYXBpZW5zLnY3NV0KICAqIGtuaXRyW0Brbml0cl0KICAqIGthYmxlRXh0cmFbQGthYmxlRXh0cmFdCiAgKiBoZWF0bWFwW0BoZWF0bWFwXQogICogY2lyY2xpemVbQGNpcmNsaXplXQogICogZ3Byb2ZpbGVyMltAZ3Byb2ZpbGVyMl0KICAKVGhlIG9iamVjdGl2ZSBvZiB0aGlzIHNlY29uZCBhc3NpZ25tZW50IGlzIHRvIGV4cGxvcmUgdGhlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBmcm9tIHRoZSBjbGVhbmVkIGFuZCBub3JtYWxpemVkIGRhdGEgaW4gQTEuIFRoZW4gcmFuayB0aGUgdGhyZXNob2xkZWQgb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyB0byBoaWdobGlnaHQgdGhlIHRvcCB0ZXJtcyAvIGRvbWluYW50IHRoZW1lcyBpbiB0aGUgdG9wIHNldCBvZiBnZW5lcy4gTGFzdGx5LCBjb21wYXJlIG15IHJlc3VsdCB3aXRoIHRoZSBvcmlnaW5hbCBsaXRlcmF0dXJlIGFuZCBmaW5kIHNvbWUgb3RoZXIgc3VwcG9ydHMgYXMgd2VsbCBmb3IgbXkgcmVzdWx0IGlmIHBvc3NpYmxlLiBJIG1ha2Ugc29tZSBjaGFuZ2VzIHRvIG15IGFzc2lnbm1lbnQgb25lIGFuZCBzdG9yZWQgdGhlIGZpbGUgYXMgImFtbWVuZGVkX0ExLlJtZCIgYW5kIGltcG9ydGVkIGl0IGhlcmUuIEkgd2lsbCBkZW1vbnN0cmF0ZSBicmllZmx5IHdoYXQgSSBoYXZlIGNoYW5nZWQgaW4gZ2VuZXJhbCB3b3JrZmxvdyBpbiBBMS4gTXkgc3VtbWFyeSBvZiB0aGUgcGFwZXIgY2FuIGJlIGZvdW5kIGF0IFtteSBqb3VybmFsXShodHRwczovL2dpdGh1Yi5jb20vYmNiNDIwLTIwMjAvc3R1ZGVudF9oZWxlbjMwNy93aWtpL2ExKSBvciBpbiBBMQoKYGBge3Igc2V0dXAyLCByZXN1bHRzPSJoaWRlIiwgaW5jbHVkZSA9IEZBTFNFLGVjaG89RkFMU0V9CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImxpbW1hIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoImxpbW1hIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQ29tcGxleEhlYXRtYXAiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQ29tcGxleEhlYXRtYXAiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJlZGdlUiIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJlZGdlUiIpCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkVuc0RiLkhzYXBpZW5zLnY3NSIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJFbnNEYi5Ic2FwaWVucy52NzUiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJrbml0ciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJrbml0ciIpCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ3Byb2ZpbGVyMiIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJncHJvZmlsZXIyIikKCmxpYnJhcnkobGltbWEpCmxpYnJhcnkoZWRnZVIpCmxpYnJhcnkoRW5zRGIuSHNhcGllbnMudjc1KQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KGdwcm9maWxlcjIpCgpgYGAKCgojIyBMb2FkIGRhdGEKTG9hZGVkIG15IG5vcm1hbGl6ZWQgZGF0YSBmcm9tIEExLgpgYGB7ciBsb2FkIG5vcm0gZGF0YX0Kbm9ybWFsaXplZF9jb3VudF9kYXRhIDwtIHJlYWQudGFibGUoZmlsZT0iR1NFODQwNTRfbm9ybWFsaXplZF9jb3VudC50eHQiKQprYWJsZShub3JtYWxpemVkX2NvdW50X2RhdGFbMTo1LCAxOjVdLCB0eXBlPSJodG1sIikKYGBgCiMjIEV4cGxvcmU6IE5vcm1hbGl6ZWQgCmBgYHtyIGJveHBsb3Rfbm9ybWFsaXplZCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBBZnRlciBub3JtYWxpemF0aW9uCmRhdGEycGxvdF9hZnRlciA8LSBsb2cyKG5vcm1hbGl6ZWRfY291bnRfZGF0YVssMzpuY29sKG5vcm1hbGl6ZWRfY291bnRfZGF0YSldKQp7Ym94cGxvdChkYXRhMnBsb3RfYWZ0ZXIsIHhsYWIgPSAiU2FtcGxlcyIsIHlsYWIgPSAibG9nMiBDUE0iLCAKICAgICAgICBsYXMgPSAyLCBjZXggPSAwLjUsIGNleC5sYWIgPSAwLjUsCiAgICAgICAgY2V4LmF4aXMgPSAwLjUsIG1haW4gPSAiRmlsdGVyZWQgYW5kIG5vcm1hbGl6ZWQgUk5BU2VxIFNhbXBsZXMiKQphYmxpbmUoaCA9IG1lZGlhbihhcHBseShkYXRhMnBsb3RfYWZ0ZXIsIDIsIG1lZGlhbikpLCBjb2wgPSAiZ3JlZW4iLCBsd2QgPSAwLjYsIGx0eSA9ICJkYXNoZWQiKX0KYGBgCgpgYGB7ciBkZW5zaXR5X25vcm1hbGl6ZWQsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvdW50c19kZW5zaXR5IDwtIGFwcGx5KGxvZzIobm9ybWFsaXplZF9jb3VudF9kYXRhWywzOm5jb2wobm9ybWFsaXplZF9jb3VudF9kYXRhKV0pLCAyLCBkZW5zaXR5KQogICNjYWxjdWxhdGUgdGhlIGxpbWl0cyBhY3Jvc3MgYWxsIHRoZSBzYW1wbGVzCiAgICB4bGltIDwtIDA7IHlsaW0gPC0gMAogICAgZm9yIChpIGluIDE6bGVuZ3RoKGNvdW50c19kZW5zaXR5KSkgewogICAgICB4bGltIDwtIHJhbmdlKGMoeGxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR4KSk7IAogICAgICB5bGltIDwtIHJhbmdlKGMoeWxpbSwgY291bnRzX2RlbnNpdHlbW2ldXSR5KSkKICAgIH0KICAgIGNvbHMgPC0gcmFpbmJvdyhsZW5ndGgoY291bnRzX2RlbnNpdHkpKQogICAgbHR5cyA8LSByZXAoMSwgbGVuZ3RoKGNvdW50c19kZW5zaXR5KSkKICAgICNwbG90IHRoZSBmaXJzdCBkZW5zaXR5IHBsb3QgdG8gaW5pdGlhbGl6ZSB0aGUgcGxvdAogICAgcGxvdChjb3VudHNfZGVuc2l0eVtbMV1dLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgdHlwZT0ibiIsIAogICAgICAgICB5bGFiPSJTbW9vdGhpbmcgZGVuc2l0eSBvZiBsb2cyLUNQTSIsY2V4LmxhYiA9IDAuODUsIAogICAgICAgICBtYWluID0gIkZpbHRlcmVkIGFuZCBub3JtYWxpemVkIFJOQVNlcSBTYW1wbGVzIGRpc3RyaWJ1dGlvbiIpCiAgICAjcGxvdCBlYWNoIGxpbmUKICAgIGZvciAoaSBpbiAxOmxlbmd0aChjb3VudHNfZGVuc2l0eSkpIGxpbmVzKGNvdW50c19kZW5zaXR5W1tpXV0sIGNvbD1jb2xzW2ldLCBsdHk9bHR5c1tpXSkKICAgIGxlZ2VuZCgidG9wcmlnaHQiLCBjb2xuYW1lcyhkYXRhMnBsb3QpLCBjb2w9Y29scywgbHR5PWx0eXMsIGNleD0wLjc1LCAKICAgICAgICAgICBib3JkZXIgPSJibHVlIiwgIHRleHQuY29sID0gImdyZWVuNCIsIG1lcmdlID0gVFJVRSwgYmcgPSAiZ3JheTkwIikKYGBgCgojIyBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiAKMS4gQ2FsY3VsYXRlIHAtdmFsdWVzIGZvciBlYWNoIG9mIHRoZSBnZW5lcyBpbiB5b3VyIGV4cHJlc3Npb24gc2V0LiBIb3cgbWFueSBnZW5lcyB3ZXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkPyBXaGF0IHRocmVzaG9sZHMgZGlkIHlvdSB1c2UgYW5kIHdoeT8KKiBUaGVyZSBhcmUgNzQ2NCBnZW5lcyB0aGF0IGFyZSBiZWxvdyB0aGUgcC12YWx1ZS4gVGhlIHRocmVzaG9sZCBJIHVzZWQgaXMgMC4wNSBiZWNhdXNlIHRoaXMgaXMgd2hhdCB0aGUgYXV0aG9ycyBvZiB0aGUgcGFwZXIgc3VnZ3Vlc3RlZCB0aGF0IHRoZXkgdXNlLgoyLiBNdWx0aXBsZSBoeXBvdGhlc2lzIHRlc3RpbmcgLSBjb3JyZWN0IHlvdXIgcC12YWx1ZXMgdXNpbmcgYSBtdWx0aXBsZSBoeXBvdGhlc2lzIGNvcnJlY3Rpb24gbWV0aG9kLiBXaGljaCBtZXRob2QgZGlkIHlvdSB1c2U/IEFuZCBXaHk/IEhvdyBtYW55IGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uPwoqIEkgdXNlZCBGRFIgY29ycmVjdGlvbiB3aGljaCBpcyBhbHNvIHdoYXQgdGhlIGF1dGhvcnMgb2YgdGhlIHBhcGVyIHNwZWNpZmllZC4gNTAzMyBnZW5lcyBwYXNzZWQgdGhlIGNvcnJlY3Rpb24uIEJvdGggdGhlIHAtdmFsdWUgYW5kIHRoZSBjb3JyZWN0aW9uIGRhdGEgYXJlIGJhc2VkIG9uIHRoZSBlZGdlUiBwYWNrYWdlLCBub3QgdGhlIGxpbW1hIHBhY2thZ2UuIEkgdXNlZCB0aGUgbGltbWEgcGFja2FnZSB1cCB0aWxsIHRoZSBwb2ludCBvZiBjYWxjdWxhdGluZyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBsaWtlIHdoYXQgaXMgc3VnZ3Vlc3RlZCBvbiB0aGUgbGVjdHVyZSBub3Rlcy4KMy4gU2hvdyB0aGUgYW1vdW50IG9mIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB1c2luZyBhbiBNQSBQbG90IG9yIGEgVm9sY2FubyBwbG90LiBIaWdobGlnaHQgZ2VuZXMgb2YgaW50ZXJlc3QuCiogSSBzaG93ZWQgYSB2b2xjYW5vIHBsb3QgdXNpbmcgbXkgZWRnZVIgZml0dGVkIGRhdGEgYW5kIGhpZ2hsaWdoZWQgdGhlIHVwcmVndWxhdGVkIHRvIGJlIHJlZCBhbmQgZG93biByZWd1bGF0ZWQgdG8gYmUgYmx1ZS4KNC4gVmlzdWFsaXplIHlvdXIgdG9wIGhpdHMgdXNpbmcgYSBoZWF0bWFwLiBEbyB5b3UgY29uZGl0aW9ucyBjbHVzdGVyIHRvZ2V0aGVyPyBFeHBsYWluIHdoeSBvciB3aHkgbm90LgoqIE15IGRhdGEgY2x1c3RlcmVkIHBlcmZlY3RseSBhY2NvcmRpbmcgdG8gdGhlaXIgY2VsbCB0eXBlcyB3aGljaCBpcyB3aGF0IG15IG1vZGVsIGRlc2lnbiBiYXNlZCBvbi4gTXkgaW50ZXJwcmV0YXRpb24gZm9yIHRoZSBncmFwaCB3b3VsZCBiZSB0aGF0IHNpbmNlIHRoZSBjb2xvcnMgYXJlIG9wcG9zaXRlIHRvIGVhY2ggb3RoZXIgaW4gdGhlIHR3byBkaWZmZXJlbnQgY2VsbCB0eXBlcywgaXQgbWVhbnMgdGhhdCB0aGUgZ2VuZXMgdGhhdCBhcmUgdXByZWd1bGF0ZWQgaW4gdHVtb3Vyc3BoZXJlIHdvdWxkIGJlIGRvd24gcmVndWxhdGVkIGluIHByaW1hcnkgdHVtb3VyIHNhbXBsZXMuIFRoZSBzaG93cyBhIGdyZWF0IHJlc3VsdHMgdGhhdCB0aGUgdXByZWd1bGF0ZWQgZ2VuZXMgY2FuIGJlIHBvdGVudGlhbCBiaW9tYXJrZXJzIHRvIHRyYWNrIGlmIHR1bW91cnNwaGVyZSBpcyBwcmVzZW50IG9yIG5vdC4KCiMjIyAxLiBDaG9pY2Ugb2YgZmFjdG9ycyBpbiBteSBtb2RlbAoqIEkgY3JlYXRlZCB0aGUgTURTIGJ5IGJvdGggdXNpbmcgImNlbGxfdHlwZSIgYW5kICJjZWxsX3R5cGUiIGFuZCAicGF0aWVudCIuIFRoZSBjb21wYXJpc29uIGJldHdlZW4gdGhlIHR3byBtb2RlbHMgaXMgZmFpcmx5IGNsZWFyOiB3ZSBzaG91bGQgb25seSBkZXBlbmQgb24gdGhlIGZhY3RvciAiY2VsbF90eXBlIiwgc2luY2UgdGhlcmUgc2VlbXMgdG8gYmUgbm8gY29ycmVsYXRpb24gd2l0aCBlYWNoIHBhdGllbnQuCgpgYGB7ciBNRFMtMSwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0gCmhlYXRtYXBfbWF0cml4IDwtIG5vcm1hbGl6ZWRfY291bnRfZGF0YVssMzpuY29sKG5vcm1hbGl6ZWRfY291bnRfZGF0YSldCnJvd25hbWVzKGhlYXRtYXBfbWF0cml4KSA8LSBub3JtYWxpemVkX2NvdW50X2RhdGEkR0VORUlECmNvbG5hbWVzKGhlYXRtYXBfbWF0cml4KSA8LSByb3duYW1lcyhzYW1wbGVzX2ZpbHRlcmVkKQoKIyBNRFMgcGxvdCBieSAiY2VsbF90eXBlIiBpbiBzYW1wbGVzCnBsb3RNRFMoaGVhdG1hcF9tYXRyaXgsIGxhYmVscz1yb3duYW1lcyhzYW1wbGVzX2ZpbHRlcmVkKSwgCiAgICAgICAgY29sID0gYygiZGFya2dyZWVuIiwiYmx1ZSIpW2ZhY3RvcihzYW1wbGVzX2ZpbHRlcmVkJGNlbGxfdHlwZSldLAogICAgICAgIG1haW4gPSAiTURTIHBsb3QgZGVwZW5kaW5nIG9uIGNlbGwgdHlwZSIpCmBgYAoKCmBgYHtyIE1EUy0yLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfSAKcGF0X2NvbG9ycyA8LSByYWluYm93KDEyKQpwYXRfY29sb3JzIDwtIHVubGlzdChsYXBwbHkocGF0X2NvbG9ycyxGVU49ZnVuY3Rpb24oeCl7cmVwKHgsMil9KSkKIyBNRFMgcGxvdCBieSAiY2VsbF90eXBlIiArICJwYXRpZW50cyJpbiBzYW1wbGVzCnBsb3RNRFMoaGVhdG1hcF9tYXRyaXgsIGNvbCA9IHBhdF9jb2xvcnMsCiAgICAgICAgbWFpbiA9ICJNRFMgcGxvdCBkZXBlbmRpbmcgb24gYm90aCBjZWxsIHR5cGUgYW5kIHBhdGllbnRzIikKYGBgCgojIyMgMi4gRGVmaW5lIG15IG1vZGVsIGRlc2lnbgpCYXNlZCBvbiB0aGUgdHdvIG1vZGVscyBpbiBwYXJ0MSwgSSBkZWNpZGUgdG8gYmFzZSBteSBtb2RlbCBvbmx5IG9uICJjZWxsX3R5cGUiCmBgYHtyIG1vZGVsfSAKbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHNhbXBsZXMkY2VsbF90eXBlKQprYWJsZShtb2RlbF9kZXNpZ24sIHR5cGU9Imh0bWwiKQpgYGAKCgojIyMgMy4gU2V0IHVwIEVkZ2VSIG9iamVjdAoKYGBge3IgZCBvYmplY3R9CmQgPSBER0VMaXN0KGNvdW50cz1maWx0ZXJlZF9kYXRhX21hdHJpeCwgZ3JvdXA9c2FtcGxlcyRjZWxsX3R5cGUpCmQgPC0gZXN0aW1hdGVEaXNwKGQsIG1vZGVsX2Rlc2lnbl9wYXQpCiNjYWxjdWxhdGUgbm9ybWFsaXphdGlvbiBmYWN0b3JzCmQgPC0gY2FsY05vcm1GYWN0b3JzKGQpCmBgYAoKIyMjIDQuIFRlc3Qgd2hldGhlciBteSBkYXRhIGlzIHN1aXRhYmxlIGZvciBlZGdlUiAtIE1lYW5WYXIgcGxvdApJIGhhdmUgc2hvd24gdGhhdCBteSBkYXRhIGlzIHN1aXRhYmxlIGZvciB1c2luZyBlZGdlUiBmb3IgZnVydGhlciBhbmFseXNpcy4gVGhlIGRhdGEgZm9sbG93cyB0aGUgYmlub21pYWwgZGlzdHJpYnV0aW9uLgpgYGB7ciBtZWFudmFyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90TWVhblZhcihkLCBzaG93LnJhdy52YXJzID0gVFJVRSwgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIHNob3cudGFnd2lzZS52YXJzPVRSVUUsICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgc2hvdy5hdmUucmF3LnZhcnMgPSBUUlVFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICBOQmxpbmU9VFJVRSwKICAgICAgICAgICAgc2hvdy5iaW5uZWQuY29tbW9uLmRpc3AudmFycyA9IFRSVUUsCiAgICAgICAgICAgIG1haW4gPSAiQmlub21pYWwgZGlzdHJpYnV0aW9uIG9mIG15IGRhdGEiKQpgYGAKCiMjIyA1LiBFc3RpbWF0ZSBkaXNwZXJzaW9uIC0gQkNWIHBsb3QKVGhlIGluZGl2aWR1YWwgZG90cyByZXByZXNlbnQgZWFjaCBnZW5lIGFuZCB0aGUgYmx1ZSBsaW5lIGlzIHRoZSBvdmVyYWxsIHRyZW5kIGxpbmUuCmBgYHtyIEJDViwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdEJDVihkLGNvbC50YWd3aXNlID0gImJsYWNrIixjb2wuY29tbW9uID0gInJlZCIsIAogICAgICAgIG1haW4gPSAiQkNWIHBsb3Qgb2YgUk5BLXNlcSBkYXRhIikKYGBgCgojIyMgNi4gR2VuZXMgcGFzcyB0aHJlc2hvbGQgYW5kIEZEUiBjb3JyZWN0aW9uIAoKSSB1c2VkIFF1YXNpLWxpa2VsaWhvb2QgbW9kZWxzIHRvIGZpdCBteSBkYXRhIGFuZCB1c2VkIFFMRlRlc3QgdG8gdGVzdCBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24uIFRoZSBRdWFzaS1saWtlbGlob29kIGNvbXBhcmVzIHR3byBjb25kaXRpb25zIChwcmltYXJ5IHR1bW91ciBhbmQgdHVtb3Vyc3BoZXJlKSBhbmQgc2hvd3MgdGhlIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcy4gVGhlIHJlc3VsdCBiZWxvdyB0aGF0IGFyZSBzb3J0ZWQgYnkgcC12YWx1ZS4gSSBhbHNvIGluc3BlY3RlZCB0aGUgbnVtYmVyIG9mIGdlbmVzIHRoYXQgc2F0aXN0eSBteSB0aHJlc2hvbGQgYW5kIGNvcnJlY3Rpb24uIEkgY2hvb3NlIHRvIHVzZSBGRFIgY29ycmVjdGlvbiBiYXNlZCBvbiB0aGUgcGFwZXIgYXMgd2VsbFtAZ29oMjAxN2Nocm9tb3NvbWVdIC4gVGhlcmUgYXJlIDc0NjcgZ2VuZXMgcGFzcyB0aGUgcC12YWx1ZSA9IDAuMDUsIGFuZCA1MDMzIGdlbmVzIHRoYXQgcGFzcyB0aGUgRkRSIGNvcnJlY3Rpb24uCmBgYHtyIHRocmVzaG9sZCBhbmQgY29ycmVjdGlvbn0KIyBmaXQgbW9kZWwKZml0IDwtIGdsbVFMRml0KGQsIG1vZGVsX2Rlc2lnbikKCiMgY2FsY3VsYXRlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uCnFsZi5zcGhlcmVfdnNfdHVtb3VyIDwtIGdsbVFMRlRlc3QoZml0LCBjb2VmPSdzYW1wbGVzJGNlbGxfdHlwZVNwaGVyZScpCmthYmxlKHRvcFRhZ3MocWxmLnNwaGVyZV92c190dW1vdXIpLCB0eXBlPSJodG1sIikKCiMgR2V0IGFsbCB0aGUgcmVzdWx0cwpxbGZfb3V0cHV0X2hpdHMgPC0gdG9wVGFncyhxbGYuc3BoZXJlX3ZzX3R1bW91ciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvcnQuYnkgPSAiUFZhbHVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRfZGF0YSkpCgojIE51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3MgdGhlIHRocmVzaG9sZCBwLXZhbHVlID0gMC4wNQojIGxlbmd0aCh3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSkpICMgNzQ2NwoKIyBOdW1iZXIgb2YgZ2VuZXMgdGhhdCBwYXNzIGNvcnJlY3Rpb24KIyBsZW5ndGgod2hpY2gocWxmX291dHB1dF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKSAjIDUwMzMKYGBgCgojIyMgNy4gVXAgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCgpJIGRldGVybWluZWQgdGhlIG51bWJlciBvZiB1cC1yZWd1bGF0ZWQgZ2VuZXMgYnkgc2VsZWN0aW5nIGV2ZXJ5IGdlbmUgdGhhdCBkb2VzIG5vdCBwYXNzIG15IHAtdmFsdWU6IDAuMDUsIGFuZCBhbHNvIGhhdmUgYSBwb3NpdGl2ZSBsb2cgZm9sZCBjaGFuZ2UuIERvd24tcmVndWxhdGVkIGdlbmVzIGFyZSBzZWxlY3RlZCBpbiB0aGUgc2FtZSB3YXkgd2l0aCBhIG5lZ2F0aXZlIGxvZyBmb2xkIGNoYW5nZS4gU3RvcmVkIHRoZXNlIGRhdGEgZm9yIGxhdGVyIGVucmljaG1lbnQgYW5hbHlzaXMgb24gZ1Byb2ZpbGVSLiAKCmBgYHtyIHVwIGFuZCBkb3duLXJlZ3VsYXRlZH0KIyBudW1iZXIgb2YgZ2VuZXMgdGhhdCBhcmUgdXAgcmVndWxhdGVkCmxlbmd0aCh3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSAKICAgICAgICAgICAgICYgcWxmX291dHB1dF9oaXRzJHRhYmxlJGxvZ0ZDID4gMCkpICMgMTg5NwoKIyBudW1iZXIgb2YgZ2VuZXMgdGhhdCBhcmUgZG93biByZWd1bGF0ZWQKbGVuZ3RoKHdoaWNoKHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1ICAKICAgICAgICAgICAgICYgcWxmX291dHB1dF9oaXRzJHRhYmxlJGxvZ0ZDIDwgMCkpICMgNTU3MAoKIyBHZXQgdGhvc2UgdXAgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCnFsZl9vdXRwdXRfaGl0c193aXRoZ24gPC0gbWVyZ2UoZXhwcl9maWx0ZXJlZFssMToyXSxxbGZfb3V0cHV0X2hpdHMsIGJ5Lng9MSwgYnkueSA9IDApCgp1cHJlZ3VsYXRlZF9nZW5lcyA8LSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJEdFTkVJRFt3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPiAwKV0KCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC1xbGZfb3V0cHV0X2hpdHNfd2l0aGduJEdFTkVJRFt3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmIHFsZl9vdXRwdXRfaGl0cyR0YWJsZSRsb2dGQyA8IDApXQoKCiMgc3RvcmUgZGF0YSAtIGFsbCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQKdW5yZWdfZ2VuZXNfY29weSA8LSBkYXRhLmZyYW1lKHVwcmVndWxhdGVkX2dlbmVzKQpkb3ducmVnX2dlbmVzX2NvcHkgPC0gZGF0YS5mcmFtZShkb3ducmVndWxhdGVkX2dlbmVzKQpuYW1lcyh1bnJlZ19nZW5lc19jb3B5KSA8LSBuYW1lcyhkb3ducmVnX2dlbmVzX2NvcHkpCmFsbF9kZSA8LSByYmluZCh1bnJlZ19nZW5lc19jb3B5LCBkb3ducmVnX2dlbmVzX2NvcHkpCmNvbG5hbWVzKGFsbF9kZSkgPC0gImFsbF9kZSIKd3JpdGUudGFibGUoeD1hbGxfZGUsCiAgICAgICAgICAgIGZpbGU9ImFsbF9leHByX2RlX2dlbmVzLnR4dCIsc2VwID0gIlx0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsY29sLm5hbWVzID0gRkFMU0UscXVvdGUgPSBGQUxTRSkKCiMgdXAgcmVndWxhdGVkCndyaXRlLnRhYmxlKHg9dXByZWd1bGF0ZWRfZ2VuZXMsCiAgICAgICAgICAgIGZpbGU9ImV4cHJfdXByZWd1bGF0ZWRfZ2VuZXMudHh0IixzZXAgPSAiXHQiLAogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSxjb2wubmFtZXMgPSBGQUxTRSxxdW90ZSA9IEZBTFNFKQoKIyBkb3duIHJlZ3VsYXRlZAp3cml0ZS50YWJsZSh4PWRvd25yZWd1bGF0ZWRfZ2VuZXMsCiAgICAgICAgICAgIGZpbGU9ImV4cHJfZG93bnJlZ3VsYXRlZF9nZW5lcy50eHQiLHNlcCA9ICJcdCIsCiAgICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFLGNvbC5uYW1lcyA9IEZBTFNFLHF1b3RlID0gRkFMU0UpCmBgYAoKIyMjIDguIFNob3cgdXAgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzCgpJIGhhdmUgc2hvd24gdGhlIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBpbiBhIHZvbGNhbm8gcGxvdCBieSBjb2xvcmluZyB0aGVtIGluIHJlZCBhbmQgYmx1ZSwgdGhlIGNvZGUgaXMgZnJvbSBbQHRvbWF0b2RhdGEyMDE3XQpgYGB7ciB1cF92b2xjYW5vLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp2b2xjYW5vRGF0YSA8LSBjYmluZChxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMsIC1sb2cxMChxbGZfb3V0cHV0X2hpdHMkdGFibGUkRkRSKSkKY29sbmFtZXModm9sY2Fub0RhdGEpIDwtIGMoImxvZ0ZDIiwgIlB2YWwiKQoKdXAgPC0gcWxmX291dHB1dF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPiAwCnBvaW50LmNvbCA8LSBpZmVsc2UodXAsICJyZWQiLCAiYmxhY2siKQpwbG90KHZvbGNhbm9EYXRhLCBwY2ggPSAxNiwgY29sID0gcG9pbnQuY29sLCBjZXggPSAwLjUsCiAgICAgbWFpbiA9ICJVcC1yZWd1bGF0ZWQgZ2VuZXMgaW4gUk5BLXNlcSBkYXRhIikKYGBgCgpgYGB7ciBkb3duX3ZvbGNhbm8sIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRvd24gPC0gcWxmX291dHB1dF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPCAwCnBvaW50LmNvbCA8LSBpZmVsc2UoZG93biwgImJsdWUiLCAiYmxhY2siKQpwbG90KHZvbGNhbm9EYXRhLCBwY2ggPSAxNiwgY29sID0gcG9pbnQuY29sLCBjZXggPSAwLjUsCiAgICAgIG1haW4gPSAiRG93bi1yZWd1bGF0ZWQgZ2VuZXMgaW4gUk5BLXNlcSBkYXRhIikKYGBgCgoKIyMjIDkuIFRlc3QgRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gLSBoZWF0bWFwCgpUbyB0ZXN0IHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiwgSSB1c2VkIHRoZSBoZWF0bWFwIGFuZCBpdCBoYXMgc2hvd24gYSBjbGVhciBkaXN0aW5jdGlvbiBiZXR3ZWVuIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcy4gVGhlcmUgaXMgYSBjbGVhciBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHByaW1hcnkgdHVtb3VyIHNhbXBsZXMgYW5kIHR1bW91cnNwaGVyZSBzYW1wbGVzLihUaGV5IGFyZSByZXZlcnNlZC4pIFRoZSBjbHVzdGVyaW5nIGlzIHZlcnkgb2J2aW91cyB0byBzaG93IHRoYXQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gZXhpc3RzLgoKYGBge3IgaGVhdG1hcCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KdG9wX2hpdHMgPC0gcm93bmFtZXMocWxmX291dHB1dF9oaXRzJHRhYmxlKVtxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlPDAuMDVdIApoZWF0bWFwX21hdHJpeF90b3BoaXRzIDwtIHQoc2NhbGUodChoZWF0bWFwX21hdHJpeFt3aGljaChyb3duYW1lcyhoZWF0bWFwX21hdHJpeCkgJWluJSB0b3BfaGl0cyksXSkpKSAKaGVhdG1hcF9tYXRyaXhfdG9waGl0cyA8LSBoZWF0bWFwX21hdHJpeF90b3BoaXRzWywgYyhncmVwKGNvbG5hbWVzKGhlYXRtYXBfbWF0cml4X3RvcGhpdHMpLHBhdHRlcm4gPSAiX1AiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwKGNvbG5hbWVzKGhlYXRtYXBfbWF0cml4X3RvcGhpdHMpLHBhdHRlcm4gPSAiX1MiKSldCgppZihtaW4oaGVhdG1hcF9tYXRyaXhfdG9waGl0cykgPT0gMCl7CiAgICBoZWF0bWFwX2NvbCA9IGNvbG9yUmFtcDIoYyggMCwgbWF4KGhlYXRtYXBfbWF0cml4X3RvcGhpdHMpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyggIndoaXRlIiwgInJlZCIpKQogICAgfSBlbHNlIHsKICAgIGhlYXRtYXBfY29sID0gY29sb3JSYW1wMihjKG1pbihoZWF0bWFwX21hdHJpeF90b3BoaXRzKSwgMCwgbWF4KGhlYXRtYXBfbWF0cml4X3RvcGhpdHMpKSwgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKICAgIH0KCmN1cnJlbnRfaGVhdG1hcCA8LSBIZWF0bWFwKGFzLm1hdHJpeChoZWF0bWFwX21hdHJpeF90b3BoaXRzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW5zID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd19kZW5kID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD1oZWF0bWFwX2NvbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd19uYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19oZWF0bWFwX2xlZ2VuZCA9IFRSVUUsKQpjdXJyZW50X2hlYXRtYXAKYGBgCgojIyBUaHJlc2hvbGRlZCBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzCkFyZSB0aGVyZSBhbnkgZ2VuZSBzZXRzIG9yIHBhdGh3YXlzIHRoYXQgYXJlIGVucmljaGVkL292ZXItcmVwcmVzZW50ZWQgb3IgZGVwbGV0ZWQvdW5kZXItcmVwcmVzZW50ZWQgaW4gbXkgbGlzdD8KIyMjIEludHJvZHVjdGlvbiB0byBQQVJUIDI6CjEuICpXaGljaCBtZXRob2QgZGlkIHlvdSBjaG9vc2UgYW5kIHdoeT8qCiogSSBjaG9zZSB0byB1c2UgZzpwcm9maWxlciBiZWNhdXNlIGl0IHNob3dzIG1lIHRoZSB0b3AgdGVybSBuYW1lcyBpbiBLRUdHLCBXUCwgR08gYW5kIFJFQUMsIHdoaWNoIGlzIGhlbHBmdWwgZm9yIG1lIHdoZW4gZGVjaWRpbmcgd2hhdCB0eXBlIG9mIGRpc2Vhc2UgaXQgaXMgbW9zdCBsaWtlbHkgdG8gYmUuCjIuICpXaGF0IGFubm90YXRpb24gZGF0YSBkaWQgeW91IHVzZSBhbmQgd2h5PyBXaGF0IHZlcnNpb24gb2YgdGhlIGFubm90YXRpb24gYXJlIHlvdSB1c2luZz8qCiogR08gYmlvbG9naWNhbCBwcm9jZXNzOiAgcmVsZWFzZXMvMjAxOS0wNy0wMQoqIEtFR0c6IEtFR0cgRlRQIFJlbGVhc2UgMjAxOS0wOS0zMAoqIFJlYWN0b21lOiBlbnNlbWJsIGNsYXNzZXM6IDIwMTktMTAtMgoqIFdpa2lQYXRod2F5czogMjAxOTA5MTAKMy4gKkhvdyBtYW55IGdlbmVzZXRzIHdlcmUgcmV0dXJuZWQgd2l0aCB3aGF0IHRocmVzaG9sZHM/KgoqIFRoZSB0aHJlc2hvbGQgZm9yIGFsbCB0aGUgcXVlcmllczogMC4wNQoqIDgyMSBnZW5lIHNldHMgYXJlIHJldHVybmVkIGZvciBhbGwgdGhlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4KKiA2MCBnZW5lIHNldHMgYXJlIHJldHVybmVkIGZvciB1cC1yZWd1bGF0ZWQgZ2VuZXMuCiogMTMzMyBnZW5lIHNldHMgYXJlIHJldHVybmVkIGZvciBkb3duLXJlZ3VsYXRlZCBnZW5lcy4KCjQuIFJ1biB0aGUgYW5hbHlzaXMgdXNpbmcgdGhlIHVwLXJlZ3VsYXRlZCBzZXQgb2YgZ2VuZXMsIGFuZCB0aGUgZG93bi1yZWd1bGF0ZWQgc2V0IG9mIGdlbmVzIHNlcGFyYXRlbHkuIEhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmUgdG8gdXNpbmcgdGhlIHdob2xlIGxpc3QgKGkuZSBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHRvZ2V0aGVyIHZzLiB0aGUgdXAtcmVndWxhdGVkIGFuZCBkb3duIHJlZ3VsYXRlZCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgc2VwYXJhdGVseSk/CiogVGhlIHVwLXJlZ3VsYXRlZCBnZW5lIHNldHMgYXJlIG1vc3RseSBjZWxsdWxhciBwcm9jZXNzZXMgYW5kIG1ldGFib2xpYyBwcm9jZXNzZXMuCiogVGhlIHRvcCB0ZXJtcyBmb3IgZG93bi1yZWd1bGF0ZWQgZ2VuZSBzZXRzIGFyZSBtb3N0bHkgc2lnbmFsaW5nIHBhdGh3YXlzIGFuZCBtZXRhYm9saWMgcHJvY2Vzc2VzLwoqIFdoZW4gcnVubmluZyB3aXRoIGJvdGggdXAgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzLCBJIGZvdW5kIHRoYXQgbW9zdCBvZiB0aGVtIGFyZSBkb21pbmF0ZWQgYnkgdGhlIG1ldGFib2xpYyBhbmQgY2VsbHVsYXIgcHJvY2Vzc2VzICh1cCByZWd1bGF0ZWQgdG9wIHRlcm1zKS4gVGhlcmVmb3JlLCBpdCBjb252aW5jZXMgbWUgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIHVwLXJlZ3VsYXRlZCBnZW5lcyBpbiB0aGUgY2FuY2VyLiBBbmQgdGhlIHJlc3VsdCBhbGlnbnMgd2l0aCB0aGUgcGFwZXIgdGhhdCBzdGF0ZXMgdGhlIGNhbmNlciBpcyBvZiBzdWJ0eXBlICJiYXNhbCIuCiogQmVsb3cgYXJlIG15IHJlc3VsdHMgZm9yIGVhY2ggdXAtcmVndWxhdGVkLCBkb3duLXJlZ3VsYXRlZCwgYW5kIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCAoYm90aCkuCgojIyMgMS4gVXAgcmVndWxhdGVkIGdlbmVzClRoZXJlIHdlcmUgbm8gUkVBQyBmb3VuZC4gSSB1c2VkIHRoZSBncHJvZmlsZXIyJ3MgZnVuY3Rpb24gdG8gcXVlcnkgZGF0YSBhbmQgYWxzbyBhdHRhY2hlZCB0aGUgc2NyZWVuc2hvdHMgdGhhdCBJIHRvb2sgb24gdGhlaXIgd2Vic2l0ZSBzaW5jZSB0aGUgcGFja2FnZSBkb2VzIG5vdCBzaG93IHRoZSBudW1iZXIgb2YgZ2VuZSBzZXRzIGVhY2ggaGFzIGZvdW5kLiAKIVtdKGltYWdlL2FsbF91cC5wbmcpCiFbXShpbWFnZS9LRUdHX3VwLnBuZykKCiFbXShpbWFnZS9XUF91cC5wbmcpCiFbXShpbWFnZS9HT191cC5wbmcpCgojIyMgMi4gRG93biByZWd1bGF0ZWQgZ2VuZXMKClRoZSBzb21lIGFuYWx5c2lzIGlzIGFwcGx5IHRvIGRvd24gcmVndWxhdGVkCiFbXShpbWFnZS9hbGxfZG93bi5wbmcpCiFbXShpbWFnZS9LRUdHX2Rvd24ucG5nKQohW10oaW1hZ2UvV1BfZG93bi5wbmcpCiFbXShpbWFnZS9HT19kb3duLnBuZykKIVtdKGltYWdlL1JFQUNfZG93bi5wbmcpCgojIyMgMy4gQWxsIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcwohW10oaW1hZ2UvYWxsX0RFLnBuZykKIVtdKGltYWdlL0tFR0dfREUucG5nKQohW10oaW1hZ2UvV1BfREUucG5nKQohW10oaW1hZ2UvR09fREUucG5nKQohW10oaW1hZ2UvUkVBQ19ERS5wbmcpCgoKIyMgSW50ZXJwcmV0YXRpb24gcXVlc3Rpb25zCjEuIERvIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc20gZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlcj8KKiBUaGUgcGFwZXIgZm91bmQgMTQwMSBnZW5lcyBiZWluZyB1cC1yZWd1bGF0ZWQgd2l0aCBmb2xkIGNoYW5nZSA+IDIgYW5kIEZEUiA8IDAuMDUuIEkgZm91bmQgMTMxMiB3aGljaCBpcyByb3VnaGx5IHNpbWlsYXIuIFRoZXkgYWxzbyBmb3VuZCB0aGF0IEFMREggZmFtaWx5IGlzIHVwLXJlZ3VsYXRlZCBhcyB3ZWxsLiBCdXQgSSBmb3VuZCAzIG9mIHRoZW0gaW4gbXkgdXByZWd1bGF0ZWQgZ2VuZXMuIFRoZSBkaXNlYXNlIGlzIGluZGljYXRlZCBhcyAzMSUgb2YgYmFzYWwtbGlrZSB0dW1vcnMsIDEyJSAoSEVSMikrIHR1bW9ycyBhbmQgMTAlIG9mIGx1bWluYWwgdHVtb3JzLCBzaW5jZSB0aGUgdG9wIHRlcm1zIG9mIG15IHVwcmVndWxhdGVkIGdlbmVzIGFyZSBtZXRhYm9saWMgcHJvY2Vzc2VzLCB0aGVyZWZvcmUsIHRoZSByZXN1bHQgYWxpZ25zIHdpdGggdGhlIHBhcGVyLgoqIFRoZSBwYXBlciBkaWQgbm90IG1lbnRpb24gYWJvdXQgdGhlIGRvd24tcmVndWxhdGVkIGdlbmVzLgpgYGB7ciBpbnRlcnByZXRhdGluIHF1ZXN0aW9ucywgcmVzdWx0cz0iaGlkZSJ9CnVwcmVndWxhdGVkX2dlbmVzX3N5bSA8LSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduJFNZTUJPTFt3aGljaChxbGZfb3V0cHV0X2hpdHMkdGFibGUkUFZhbHVlIDwgMC4wNSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJiBxbGZfb3V0cHV0X2hpdHMkdGFibGUkbG9nRkMgPiAxKV0KCmxlbmd0aCh1cHJlZ3VsYXRlZF9nZW5lc19zeW0pICMgMTMxMgoKCnVwcmVndWxhdGVkX2dlbmVzX3N5bVtncmVwKHBhdHRlcm49IkFMREgiLHVwcmVndWxhdGVkX2dlbmVzX3N5bSldCiMgQUxESDIsIEFMREg4QTEsIEFMREgxTDIgLT4gY29uZmlybWVkIQpgYGAKCjIuIEV2aWRlbmNlIHRoYXQgc3VwcG9ydCBhbmQgaG93IHRoZXkgc3VwcG9ydCB5b3VyIHJlc3VsdHMuCgoqIE15IHJlc3VsdCAjMTogQUxESCBmYW1pbHkgaXMgZm91bmQgaW4gbXkgdXAgcmVndWxhdGVkIGdlbmVzLgpWZXJpZmljYXRpb24gb2Ygb3Zlci1yZXByZXNlbnRhdGlvbiBvZiBBTERIIGlzIGFuIGltcG9ydGFudCBmYW1pbHkgaW4gYnJlYXN0IGNhbmNlciBieSBbQHZhc3NhbGxpMjAxOWFsZGVoeWRlXS4gVGhleSBjb25zaWRlciBBTERIIGZhbWlseSBhcyBhIGJpb21hcmtlciBmb3IgYnJlYXN0IGNhbmNlciB3aGljaCBzdWdndWVzdHMgdGhhdCBteSByZXN1bHQgKHRoZSBmYWN0IHRoYXQgdXAtcmVndWxhdGVkIGdlbmVzIGNvbnRhaW5zIHRoZSBBTERIIGZhbWlseSBpcyB2ZXJpZmllZCkuIAoqIE15IHJlc3VsdCAjMjogdG9wIHRlcm1zIG9mIHRoZSB1cHJlZ3VsYXRlZCBnZW5lcyBhcmUgbW9zdGx5IGNlbGx1bGFyIGFuZCBtZXRhYm9saWMgcHJvY2Vzc2VzLgpbQHZhc2lsaW91MjAwNWFuYWx5c2lzXSBjb252aW5jZXMgbWUgdGhhdCBteSByZXN1bHQgZnJvbSBnOnByb2ZpbGVyIG1hdGNoZXMgd2l0aCB0aGUgYmFzYWwgc3VidHlwZS4gVGhlIHBhcGVyIHN0YXRlcyB0aGF0IG11dGF0aW9ucyBpbiBBTERIIGdlbmVzIGNhdXNlcyBtZXRhYm9saXNtIGVycm9ycywgZm9yIGV4YW1wbGUsIFNqw7ZncmVuIC0gTGFyc3NvbiBzeW5kcm9tZSwgdHlwZSBJSSBoeXBlcnByb2xpbmFlbWlhIGFuZCDOsy1oeWRyb3h5YnV0eXJpYyBhY2lkdXJpYSBhbmQgZXZlbiBjYW5jZXIgYW5kIEFsemhlaW1lcidzIGRpc2Vhc2UuIAoKCiMgUGFydCAzOiBub24tdGhyZXNob2xkZWQgKyBuZXR3b3JrIGFuYWx5c2lzClRoZSBvYmplY3RpdmUgb2YgdGhpcyB0aGlyZCBhc3NpZ25tZW50IGlzIHRvIHVzZSB0aGUgcmFua2VkIGZpbGUgZnJvbSBBMiBhbmQgcGVyZm9ybSBub24tdGhyZXNob2xkZWQgYW5hbHlzaXMgd2l0aCBHU0VBIChWZXJzaW9uIDQuMC4zKSBbQEdTQV0uIFRoZW4gdGhlIHJlc3VsdCBpcyBjb21wYXJlZCB0byB0aGUgcmVzdWx0IGZyb20gdGhyZXNob2xkZWQgYW5hbHlzaXMgaW4gQTIuIEZpbmFsbHksIGN5dG9zY2FwZSAoVmVyc2lvbiAzLjcuMiwgSmF2YSAxLjguMF8xNjIgYnkgT3JhY2xlIENvcnBvcmF0aW9uKVtAbG9wZXMyMDEwY3l0b3NjYXBlXSBpcyB1c2VkIHRvIGhlbHAgdG8gY3JlYXRlIGEgdmlzdWFsaXphdGlvbiBvZiB0aGUgdXAgYW5kIGRvd24gcmVndWxhdGVkIGdlbmVzIGFsb25nIHdpdGggYW5ub3RhdGlvbnMgZnJvbSB0aGUgQmFkZXIgbGFiLiBQb3N0IGFuYWx5c2lzIGlzIHBlcmZvcm1lZCB3aXRoIGRydWdCYW5rIGRhdGFzZXRzIGZyb20gQmFkZXIgbGFiIGFzIHdlbGwuIE90aGVyIGRldGFpbHMgc3VjaCBhcyBwZXJmb3JtaW5nIHRoZSBhbmFseXNpcyBvZiBjeXRvc2NhcGUgY2FuIGJlIHJldHJpZXZlZCBmcm9tIFtteSBKb3VybmFsXShodHRwczovL2dpdGh1Yi5jb20vYmNiNDIwLTIwMjAvc3R1ZGVudF9oZWxlbjMwNy93aWtpL2EzKQoKUiBMaWJyYXJpZXMgdXNlZDogCgoqIFJDdXJsW0BSQ3VybF0KKiBrbml0cltAa25pdHJdCioga2FibGVFeHRyYVtAa2FibGVFeHRyYV0KKiBHU0FbQEdTQV0KCmBgYHtyIHNldHVwMywgcmVzdWx0cz0iaGlkZSIsIGluY2x1ZGUgPSBGQUxTRSxlY2hvPUZBTFNFfQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIlJDdXJsIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJHU0EiKQoKaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikKCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpewogICAgaW5zdGFsbC5wYWNrYWdlcygia2FibGVFeHRyYSIpCn0KCmxpYnJhcnkoUkN1cmwpCmxpYnJhcnkoR1NBKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmBgYAojIyBOb24tdGhyZXNob2xkZWQgR2VuZSBzZXQgRW5yaWNobWVudCBBbmFseXNpcwpBcmUgdGhlcmUgYW55IGdlbmUgc2V0cyBvciBwYXRod2F5cyB0aGF0IGFyZSByYW5rZWQgc3VycHJpc2luZ2x5IGhpZ2ggb3IgbG93IGluIG15IHJhbmtlZCBsaXN0PwoKIyMjIDEuR2V0IEJhZGVyIGxhYiBnZW5lIHNldHMKKiBUaGUgY29kZSBpcyBpbnNwaXJlZCBieSBsZWN0dXJlIG5vdGVzOiBub24tdGhyZXNob2xkZWQgYW5hbHlzaXMgdW5pdC4KYGBge3IsIHdhcm5pbmc9RkFMU0V9CmdtdF91cmwgPSAiaHR0cDovL2Rvd25sb2FkLmJhZGVybGFiLm9yZy9FTV9HZW5lc2V0cy9jdXJyZW50X3JlbGVhc2UvSHVtYW4vc3ltYm9sLyIKIyBsaXN0IGFsbCB0aGUgZmlsZXMgb24gdGhlIHNlcnZlcgpmaWxlbmFtZXMgPSBnZXRVUkwoZ210X3VybCkKdGMgPSB0ZXh0Q29ubmVjdGlvbihmaWxlbmFtZXMpCmNvbnRlbnRzID0gcmVhZExpbmVzKHRjKQpjbG9zZSh0YykKIyBnZXQgdGhlIGdtdCB0aGF0IGhhcyBhbGwgdGhlIHBhdGh3YXlzIGFuZCBkb2VzIG5vdCBpbmNsdWRlIHRlcm1zIGluZmVycmVkIGZyb20KIyBlbGVjdHJvbmljIGFubm90YXRpb25zKElFQSkgc3RhcnQgd2l0aCBnbXQgZmlsZSB0aGF0IGhhcyBwYXRod2F5cyBvbmx5CnJ4ID0gZ3JlZ2V4cHIoIig/PD08YSBocmVmPVwiKSguKi5HT0JQX0FsbFBhdGh3YXlzX25vX0dPX2llYS4qLikoLmdtdCkoPz1cIj4pIiwgY29udGVudHMsIAogICAgcGVybCA9IFRSVUUpCmdtdF9maWxlID0gdW5saXN0KHJlZ21hdGNoZXMoY29udGVudHMsIHJ4KSkKZG93bmxvYWQuZmlsZShwYXN0ZShnbXRfdXJsLCBnbXRfZmlsZSwgc2VwID0gIiIpLCBkZXN0ZmlsZSA9IGRlc3RfZ210X2ZpbGUpCmBgYAoKIyMjIDIuIENvbXB1dGUgcmFua3MgCiogSSBvYnRhaW5lZCB0aGUgcmFuayBmaWxlLCBjb21wdXRlZCB0aGUgcmFua3MgYW5kIHNvcnRlZCB0YWJsZSBieSByYW5rcy4gVGhlIG91dHB1dCBmaWxlIGlzICJleHByX1JOQXNlcV9yYW5rcy5ybmsiIHdoaWNoIGlzIHRvIGJlIGxvYWRlZCBpbnRvIEdTRUEgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuCiogcmFuayA9IC1sb2cxMChwLXZhbCkqc2lnbihsb2dGQykKCmBgYHtyfQojIGNvbXB1dGUgcmFua3MKcWxmX291dHB1dF9oaXRzX3dpdGhnblssInJhbmsiXSA8LSBsb2cocWxmX291dHB1dF9oaXRzX3dpdGhnbiRQVmFsdWUsIGJhc2UgPSAxMCkgKiBzaWduKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kbG9nRkMpCgojIHNvcnQgdGFibGUgYnkgcmFua3MKcWxmX291dHB1dF9oaXRzX3dpdGhnbiA8LSBxbGZfb3V0cHV0X2hpdHNfd2l0aGduW29yZGVyKHFsZl9vdXRwdXRfaGl0c193aXRoZ24kcmFuayksXQoKIyB3cml0ZSBnZW5lIG5hbWUgYW5kIHJhbmsgdG8gdGFibGUKd3JpdGUudGFibGUoeD1xbGZfb3V0cHV0X2hpdHNfd2l0aGduWywgYygyLCBuY29sKHFsZl9vdXRwdXRfaGl0c193aXRoZ24pKV0sCiAgICAgICAgICAgIGZpbGU9ImV4cHJfUk5Bc2VxX3JhbmtzLnJuayIsc2VwID0gIlx0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsY29sLm5hbWVzID0gRkFMU0UscXVvdGUgPSBGQUxTRSkKa2FibGUoaGVhZChxbGZfb3V0cHV0X2hpdHNfd2l0aGduKSwgY2FwdGlvbiA9ICJFeHByX1JOQXNlcV9yYW5rcyIsIGZvcm1hdD0iaHRtbCIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAiaG92ZXIiKQpgYGAKCgoKIyMjIDMuIENvbmR1Y3Qgbm9uLXRocmVzaG9sZGVkIGdlbmUgc2V0IGVucmljaG1lbnQgYW5hbHlzaXMKCkkgdXNlZCB0aGUgY29tcHV0ZWQgcmFua2VkIHNldCBvZiBnZW5lcyB0byBjb21wdXRlIHRoZSBub24tdGhyZXNob2xkZWQgZ2VuZSBzZXQgZW50aWNobWVudCBhbmFseXNpcyB3aXRoIEdTRUFfNC4wLjMuW0BHU0FdIEkgbG9hZGVkIHRoZSByYW5rIGZpbGUgImV4cHJfUk5Bc2VxX3JhbmtzLnJuayIgYW5kIEJhZGVyIExhYiBnZW5lIHNldCAiaHVtYW5fR09CUF9BbGxQYXRod2F5c19ub19HT19pZWFfTWFyY2hfMDFfMjAyMF9zeW1ib2wuZ210Ii4gVGhlIHBhcmFtZXRlcnMgYXJlIHBlcm11dGF0aW9uID0gMTAwLCBubyBjb2xsYXBzZSwgbWF4ID0gMjAwLCBtaW4gPSAxNS4gVGhlIGZpbGUgb2J0YWluZWQgaXM6ICJBM19wYXJ0MV9ub25fdGhyZXMuR3NlYVByZXJhbmtlZC4xNTg0NDY5Mzk4OTc2Ii4gSGVyZSBpcyBhIHNjcmVlbnNob3QgYmVmb3JlIHBlcmZvcm1pbmcgdGhlIGFuYWx5c2lzIG9uIEdTRUEuCiFbXShpbWFnZS9nc2VhX2JlZm9yZS5wbmcpCgoKIyMjIDQuIFN1bW1hcml6ZSBlbnJpY2htZW50IHJlc3VsdHMKCk15IGRhdGEgaXMgZGl2aWRlZCBpbnRvICJQT1MiIGFuZCAiTkVHIiB3aGljaCBjb3JyZXNwb25kIHRvIHVwLXJlZ3VsYXRlZGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcy4gCgoqIEZvciB0aGUgIlBPUyIgZ3JvdXAsIAogICogSHVtb3JhbCBpbW11bmUgcmVzcG9uc2UgaXMgdGhlIHRvcCB0ZXJtIAogICogUC12YWwgPSAwLCAKICAqIDkgZ2VuZXMgaW4gaXRzIGxlYWRpbmcgZWRnZQogICogVGhlIHRvcCBnZW5lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGdlbmVzZXQgaXMgSUdLVjJELTI4LiAKCmBgYHtyLCBlY2hvPUZBTFNFfQpwb3MgPC0gcmVhZC5kZWxpbSgiL1VzZXJzL2hlbGVuZGluZy9EZXNrdG9wL2JjYjQyMC9nc2VhX3Jlc3VsdC9nc2VhX3JlcG9ydF9mb3JfbmFfcG9zXzE1ODQ0NjkzOTg5NzYueGxzIikKa2FibGUoaGVhZChuZWdbLGMoMSwgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExKV0pLCBjYXB0aW9uID0gIkRvd24tcmVndWxhdGVkX3RvcF90ZXJtcyIsIGZvcm1hdD0iaHRtbCIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAiaG92ZXIiKQpgYGAKCiogSW4gdGhlICJORUciIGdyb3VwLCAKICAqIFRHRiBiZXRhIHJlY2VwdG9yIGlzIHRoZSB0b3AgdGVybQogICogUC12YWwgPSAwCiAgKiAxODUgZ2VuZXMgaW4gaXRzIGxlYWRpbmcgZWRnZQogICogVGhlIHRvcCBnZW5lIGFzc29jaWF0ZWQgd2l0aCBpcyBQUktDQi4KCmBgYHtyLCBlY2hvPUZBTFNFfQpuZWcgPC0gcmVhZC5kZWxpbSgiL1VzZXJzL2hlbGVuZGluZy9EZXNrdG9wL2JjYjQyMC9nc2VhX3Jlc3VsdC9nc2VhX3JlcG9ydF9mb3JfbmFfbmVnXzE1ODQ0NjkzOTg5NzYueGxzIikKa2FibGUoaGVhZChuZWdbLGMoMSwgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExKV0pLCBjYXB0aW9uID0gIkRvd24tcmVndWxhdGVkX3RvcF90ZXJtcyIsIGZvcm1hdD0iaHRtbCIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAiaG92ZXIiKQpgYGAKCiMjIyA1LiBDb21wYXJlIHRvIHRoZSByZXN1bHRzIGZyb20gdGhyZXNob2xkZWQgYW5hbHlzaXMKCkkgdXNlZCBnOnByb2ZpbGVyIGluIEEyIHRvIGNvbmR1Y3QgdGhyZXNob2xkZWQgYW5hbHlzaXMuIFRoZSByZXN1bHQgc2hvd2VkIHRoYXQgYm90aCB0aGUgdXAtcmVndWxhdGVkIGFuZCB0aGUgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgaGF2ZSBtZXRhYm9saWMgdGVybXMgYXNzb2NpYXRlZC4gV2hlcmVhcyB1c2luZyB0aGUgbm9uLXRocmVzaG9sZGVkIG1ldGhvZHMsIGltbXVuZSByZXNwb25zZSBzZWVtcyB0byBiZSBhc3NvY2lhdGVkIHdpdGggdXAtcmVndWxhdGVkIGdlbmVzLiBCZXRhLXJlY2VwdG9yIHNlZW1zIHRvIGJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZG93bi1yZWd1bGF0ZWQgZ3JvdXAgd2hpY2ggaXMgdGhlIHNhbWUgYXMgdGhlIHJlc3VsdCBmcm9tIGc6cHJvZmlsZXIuIEJvdGggdGhyZXNob2xkZWQgYW5kIG5vbi10aHJlc2hvbGRlZCBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHNob3dzIHRoYXQgdGhlIGRpc2Vhc2UgaXMgYXNzb2NpYXRlZCB3aXRoIGltbXVuZSByZXNwb25zZSBhbmQgbWV0YWJvbGljIG1hbGZ1bmN0aW9ucy4gU3VjaCByZXN1bHQgaXMgY29uc2lzdGVudCB3aXRoIHRoZSByZXN1bHQgZnJvbSB0aGUgcGFwZXIsIGFuZCBJIGhhdmUgZm91bmQgc29tZSBvZiB0aGUgZXZpZGVuY2VzIGZyb20gdGhlIG90aGVyIHBhcGVycyBpbiBBMiwgc2hvd2luZyB0aGF0IGJyZWFzdCBjYW5jZXIgaXMgYXNzb2NpYXRlZCB3aXRoIHRoZXNlIHRvcCB0ZXJtcy4KCgojIyBWaXN1YWxpemUgR2VuZSBzZXQgRW5yaWNobWVudCBBbmFseXNpcwoKIyMjIDEuIENyZWF0ZSBhbiBlbnJpY2htZW50IG1hcAoKKiBUaGUgZm9sbG93aW5nIHZpc3VhbGl6YXRpb24gaXMgY29uZHVjdGVkIHVzaW5nIEN5dG9zY2FwZSBbQGxvcGVzMjAxMGN5dG9zY2FwZV0KKiBUaGUgcGFyYW1ldGVycyBJIHVzZWQgd2hlbiBjcmVhdGluZyB0aGUgZW5yaWNobWVudCBtYXA6IEZEUiB3YXMgc2V0IHRvIDAuMDEsIG90aGVycyBhcmUga2VwdCBhcyBkZWZhdWx0LgoqIEJhc2ljIGluZm9ybWF0aW9uOiB0aGVyZSBhcmUgNDU2IG5vZGVzIGFuZCA1MDg3IGVkZ2VzIGluIHRoZSByZXN1bHRpbmcgbWFwLgoqIEhlcmUgaXMgYSBzY3JlZW5zaG90IHRoYXQgZ2l2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGNyZWF0aW9uIG9mIHRoZSBlbnJpY2htZW50IG1hcC4KIVtdKGltYWdlL2NyZWF0aW9uX2VucmljaG1lbnRfbWFwLnBuZykKCiMjIyAyLiBBbm5vdGF0ZSB0aGUgZW5yaWNobWVudCBtYXAKCkkgZGVmaW5lZCB0aGUgbWFpbiBiaW9sb2dpY2FsIHRoZW1lcyBieSB1c2luZyBjbGlja2luZyBvbiAiYXV0byBhbm5vdGF0ZSIgLT4gImFubm90YXRlIi4gVGhlIHN5c3RlbSBjcmVhdGVkIGNpcmNsZXMgYXJvdW5kIGVhY2ggY2x1c3RlciB3aGljaCBjb3JyZXNwb25kcyB0byB0aGUgbW9zdCBmcmVxdWVudCBub2RlIGxhdmxlcyBpbiB0aGUgY2x1c3Rlci4gSGVyZSBpcyBhIHNjcmVlbnNob3Qgb2YgdGhlIG92ZXJ2aWV3LgohW10oaW1hZ2Uvb3ZlcnZpZXdfY3l0b3NjYXBlLnBuZykKCiMjIyAzLiBNYW51YWxseSBlZGl0IHRoZSBuZXR3b3JrCgoqIEkgbWFkZSBzdXJlIHRoYXQgdGhlcmUgaXMgbm8gb3ZlcmxhcCBiZXR3ZWVuIHRoZSBsYWJlbHMgYW5kIHRoZSBub2Rlcy4gSSBhbHNvIG9yYWduaXplZCB0aGVtIHRvIG1ha2UgdGhlIGludGVyYWN0aW9ucyBjbGVhcmVyLiBUaGUgbGVnZW5kIGlzIG9idGFpbmVkIGZyb20gQmFkZXIgbGFiJ3Mgd2Vic2l0ZS4gCiogSSBkaWQgbm90IHNjcmVlbnNob3QgdGhlIG5ldHdvcmsgc2luY2UgaXQgaXMgdGhlIHNhbWUgYXMgdGhlIHJlc3VsdGluZyBncmFwaCB0aGF0IGFsc28gY29udGFpbnMgdGhlIHR3byBkcnVncyBJIHBpY2tlZC4gVGhlIHNjcmVlbnNob3QgY2FuIGJlIGZvdW5kIGluIHRoZSBzZWN0aW9uOiAiIFBvc3QgYW5hbHlzaXMgLSBEcnVnIEJhbmsiLgoKIyMjIDQuIENvbGxhcHNlIHRvIGEgdGhlbWUgbmV0d29yawoqIEdlbmVyYWxseSwgdGhlIG1ham9yIHRoZW1lcyBJIGZvdW5kIGFmdGVyIGNvbGxhcHNpbmcgdGhlIGFubm90YXRlZCBuZXR3b3JrOiBpbW11bmUgcmVzcG9uc2VzLCBjZWxsIHByb2xpZmVyYXRpb24sIHRhZ2V0aW5nLCBhbmQgc2lnbmFsaW5nLlRoZXJlIHNlZW1zIHRvIGJlIG5vIG5vdmVsIHBhdGh3YXlzLiAKKiBIZXJlIGlzIGFuIG92ZXJ2aWV3IG9mIHRoZSBjb2xsYXBzZWQgZ3JhcGguCgohW10oaW1hZ2UvY3JvcHBlZF9ub19kcnVnX2NvbGxhcHNlZC0xLnBuZykKCiMjIyA1LiBJbnRlcnByZXRhdGlvbiBvZiB0aGUgYW5ub3RhdGVkIG5ldHdvcmsKKiBUZXJtcyBvbiB0aGUgbGVmdCBhcmUgdXAtcmVndWxhdGVkIGdlbmVzIGFuZCB0ZXJtcyBvbiB0aGUgcmlnaHQgYXJlIGRvd24tcmVndWxhdGVkIGdlbmVzLiBUaGUgbGluZXMgc2hvd3MgdXMgdGhlIGludGVyYWN0aW9ucyBiZXR3ZWVuIGVhY2ggbW9zdCBmcmVxdWVudCB0ZXJtcy4KKiBPbiB0aGUgbGVmdCBzaWRlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIHRlcm0gdGhhdCBoYXMgdGhlIG1vc3QgaW50ZXJhY3Rpb25zIHdpdGggdGhlIHJlc3QgaXMgInJlc3BvbnNlIGltbXVuZSBpbW11bm9nbG9idWxpbiIuIEl0IGlzIGNvbm5lY3RlZCB0byB0ZXJtcyBsaWtlICJseW1waG9jeXRlIHByb2xpZmVyYXRpb24iLCAiZGlmZmVyZW50aWF0aW9uIiwgIm5lZ2F0aXZlIGNlbGwgcmVndWxhdGlvbiIsICJzaWduYWxpbmciLCBldGMuIEVsZXZhdGVkIGxldmVsIGltbXVub2dsb2J1bGluIGFudGlib2RpZXMgaXMgZnJlcXVlbnRseSBvYnNlcnZlZCBpbiBjYW5jZXJzIG9mIGVwaXRoZWxpYWwgb3JpZ2luLCBpbmNsdWRpbmcgY2FyY2lub21hcyBvZiBicmVhc3QsIGNvbG9uLCBhbmQgbGl2ZXIuW0BxaXUyMDAzaHVtYW5dIFRoZXJlZm9yZSwgaXQganVzdGlmaWVzIHRoZSByZWFzb24gd2h5IHRoaXMgdGVybSBpcyB1cC1yZWd1bGF0ZWQuCiogT24gdGhlIHJpZ2h0IHNpZGUsIHdlIG5vdGljZSB0aGUgbWFpbiB0ZXJtIGlzICJBUEMgZGVkZWdyYWRhdGlvbiIgKHdpdGggdGhlIG1vc3QgZ2VuZXMpLiBBbnRpZ2VuIHByZXNlbnRpbmcgY2VsbHMgKEFQQ3MpIGFyZSBpbW11bmUgY2VsbHMgdGhhdCBzcGVjaWFsaXplIGluIHByZXNlbnRpbmcgYW4gYW50aWdlbiB0byBhIFQtY2VsbC4gQVBDIHByb3RlaW4gYWN0cyBhcyBhIHR1bW9yIHN1cHByZXNzb3IsIHRoZXJlZm9yZSwgdGhlIGRlZ3JhZGF0aW9uIG9mIEFQQyBtZWFucyB0aGF0IHRoZSBzdXBwcmVzc29yIGlzIG5vIGxvbmdlciBmdWxseSBzdXBwbGllZCB3aGljaCBjYW4gbm90IHN0b3AgdGhlIGRpc2Vhc2UgZnJvbSBleHBhbmRpbmcuIE90aGVyIHRlcm1zIGFyZSByZWxhdGVkIHRvIGNlbGwgKiB0cmFuc3BvcnQsIGV0Yy4KKiBJbiBjb25jbHVzaW9uLCB0aG9zZSB0ZXJtcyBhcmUgcHJlZGljdGVkIGJ5IHRoZSBnOnByb2ZpbGVyIGluIEEyIGV2ZW4gaWYgdGhleSBkb24ndCBoYXZlIHRoZSBleGFjdCBzYW1lIG5hbWVzLiBUaGVyZWZvcmUsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZSBkaXNlYXNlIGlzIG1vc3RseSBkdWUgdG8gaW1tdW5lIHJlc3BvbnNlIG1hbGZ1bmN0aW9uLCB3aGljaCB0aGVuIGxlYWRzIHRvIHByb2JsZW1zIGluIGNlbGwgbWV0YWJvbGlzbSBpbiB2YXJpb3VzIHdheXMuCgojIyMgNi4gUG9zdCBhbmFseXNpcyAtIERydWcgQmFuawoKVGhlIHJlYXNvbiB3aHkgSSBjaG9vc2UgdG8gZG8gdGhlIHBvc3QgYW5hbHlzaXMgd2l0aCBkcnVncyBpcyBiZWNhdXNlIHRoZSBwYXBlciBtZW50aW9uZWQgYWJvdXQgZmluZGluZyBhIHRhcmdldCBmb3IgYSBkcnVnLiBUaGUgZHJ1ZyBpcyBQYWNyaXRpbmliLiBIb3dldmVyLCB0aGlzIGRydWcgaXMgbm90IGFubm90YXRlZCwgYW5kIHRodXMgbm90IHN0b3JlZCBpbiB0aGUgQmFkZXIgTGFiIGZpbGUuIFRoZXJlZm9yZSwgSSBjaG9zZSB0aGUgdG9wIGRydWcgKEFiY2l4aW1hYikgW0BsYXcyMDE0ZHJ1Z2JhbmtdIGZyb20gQmFkZXIgbGFiIGFwcHJvdmVkIGRydWdzIGZpbGUuIFRoZSBwYXBlciBhbHNvIG1lbnRpb25lZCB0aGF0IHRoZXkgdXNlIEdlbWNpdGFiaW5lIHRvIHRyZWF0IGJyZWFzdCBjYW5jZXIgaWYgdGhlIGRpc2Vhc2UgZG9lcyBub3QgZXhwYW5kIGZ1cnRoZXIuIAoKKiBQYXJhbWV0ZXJzOiBNYW5uIFdoaXRlbmV5KE9uZS1zaWRlZCBncmVhdGVyKTogc2luY2UgSSBkbyBub3QgY2FyZSB3aGV0aGVyIGl0IHRhcmdldHMgdGhlIHVwLXJlZ3VsYXRlZCBvciBkb3duLXJlZ3VsYXRlZCBnZW5lcy4KCiogVGhlIHJlc3VsdGluZyBncmFwaCBzaG93cyB0aGF0IHRoZXJlIGFyZSBubyBjb25uZWN0aW9uIGZvciBHZW1jaXRhYmluZSB3aXRoIGFueSBwYXRod2F5cywgYW5kIGEgbG90IG9mIHVwLXJlZ3VsYXRlZCBnZW5lcyBhcmUgdGFyZ2V0ZWQgYnkgQWJjaXhpbWFiLiBUaGUgdGVybXMgdGhhdCBhcmUgdGFyZ2V0ZWQgYXJlIG1vc3RseSB0aGUgdXAtcmVndWxhdGVkIGdlbmVzLCBzdWNoIGFzICJyZXNwb25zZSBpbW11bmUgaW1tdW5vZ2xvYmluIiwgdG8gcmVkdWNlIHRoZSBlbGV2YXRlZCBsZXZlbCBvZiB0aGUgYW50aWJvZHkuIEl0IGFsc28gcmVkdWNlcyB0aGUgbGV2ZWwgb2Ygb3RoZXIgY2VsbCBtZXRhYm9saWMgdGVybXMgdGhhdCBhcmUgaW4gdGhlIHNhbWUgcGF0aHdheSBhcyB0aGUgInJlc3BvbnNlIGltbXVuZSBpbW11bm9nbG9iaW4iIChkaXNjdXNzZWQgaW4gdGhlIHNlY3Rpb24gYWJvdmUpLiBUaGUgbWFpbiBmdW5jdGlvbiBvZiB0aGlzIGRydWcgaXMgdG8gcmVkdWNlIGFudGlib2RpZXMsIGFuZCBvdGhlciBvdmVyLXByb2R1Y2VkIG1vbGVjdWxlcywgYnV0IG5vdCBlbGV2YXRpbmcgdGhlIHdlYWsgdGVybXMgKHRoZSBkb3duLXJlZ3VsYXRlZCBnZW5lcykuIAoKKiBUaGUgb25seSB0aGluZyBub3QgZXhwZWN0ZWQgaXMgdGhhdCBHZW1jaXRhYmluZSBkb2VzIG5vdCB0YXJnZXQgdGhlIHRlcm0gImNlbGwgcHJvbGlmZXJhdGlvbiBwb3NpdGl2ZSIgd2hpY2ggaXMgd2hhdCB0aGUgbWFpbiBvYmplY3Qgb2YgR2VtY2l0YWJpbmUuIEdlbWNpdGFiaW5lIGlzIGEgZHJ1ZyB0aGF0IGtpbGxzIHRoZSBmYXN0LWdyb3dpbmcgY2VsbHMuIFRoZXJlZm9yZSwgaXQgaXMgbm90IGV4cGVjdGVkIHRvIHNlZSB0aGF0IHRoaXMgZHJ1ZyBkb2VzIG5vdGhpbmcgaW4gdGhpcyBkaXNlYXNlIHBhdGh3YXkuCgoqIEl0IG1pZ2h0IGJlIGhhcmQgdG8gc2VlIHRoZSBHZW1jaXRhYmluZSwgaXQgaXMgcmlnaHQgYmVzaWRlIEFiY2l4aW1hYiwuCiFbXShpbWFnZS9wdWJsaWNhdGlvbl9maWd1cmUucG5nKQoKIVtdKGltYWdlL2Nyb3BwZWRfbm9fZHJ1Z19jb2xsYXBzZWQtMS5wbmcpCgojIFJlZmVyZW5jZXMK